
Zendesk Guide のセクションテンプレートで content_tags を表示する構成(Lambda + JS)
概要
本記事では、Zendesk Guide のセクションページに「コンテンツタグ(content tags)」を表示する方法について検証した内容を紹介します。
Zendesk の記事には「ラベル(label)」とは別に「コンテンツタグ(content tags)」という分類機構があります。これは、記事やコミュニティ投稿に一貫したタグ付けを行うことで、関連コンテンツを束ねたり、検索体験を向上させたりするための機能です。
しかし、テンプレートカスタマイズの観点から見ると、このコンテンツタグは意外とクセがあります。たとえば section_page.hbs
(=特定セクション内の記事一覧を表示するテンプレート)では、各記事オブジェクトに content_tag_ids
が含まれておらず、単純に {{#each section.articles}}
でループしてもタグ情報を参照することはできません。この制約を回避するための方法としては、JavaScript で API を非同期に呼び出す方法が挙げられます。Zendesk API への認証が必要となるため、別途サーバーサイドの実装が必要です。
本記事ではその一例として、AWS Lambda を用いた Proxy API を活用し、テンプレート側でタグを描画する仕組みを紹介します。
対象読者
- Zendesk Guide のカスタマイズを業務で担当しているエンジニアの方
- セクションページなどに追加情報(タグ・属性)を表示したいが、テンプレート上で取得できず困っている方
- AWS Lambda や API Gateway を用いて Zendesk API を拡張的に活用したい方
想定ユースケース
本構成は以下のような場面での活用を想定しています:
ユースケース | 説明 |
---|---|
リージョン・言語別の FAQ 管理 | #jp , #us などのタグを記事に付与し、対象ユーザー層を明示 |
機能別ドキュメント分類 | #API , #UI , #beta などをタグで表示し、視認性を高める |
社内ナレッジのフィルタリング | 「社内限定」「外部向け」などの情報分類を可視化したい場合 |
タグはあくまで「分類と強調表示」を目的とするため、Zendesk の「セクション」や「カテゴリ」とは補完関係にあります。
コンテンツの粒度や公開対象が増えてくると、こうしたタグによる補助的な構造が重要になってきます。
用語と構成の前提知識
用語 | 説明 |
---|---|
content_tags | Zendesk Guide Enterprise プランで利用可能なタグ分類機能。API 経由で記事との関連付けが可能 |
section_page.hbs | Zendesk のテーマテンプレートの一部で、特定セクション内の記事一覧を描画するテンプレート |
label_names | 記事に付与可能なラベル(公開用キーワード)。テンプレートから直接参照可能だが、content_tagsとは用途が異なる |
AWS Lambda | サーバーレスで JavaScript/Node.js の処理を実行できるマネージドサービス |
API Gateway | HTTP 経由で Lambda を呼び出すためのエンドポイントを作成できる AWS サービス |
Lambda を用いた Proxy API の構成と実装
クライアントサイドから Zendesk API を直接叩けない制約を回避するため、今回は AWS Lambda + API Gateway を用いた Proxy API を実装しました。Lambda は認証済みのバックエンドとして動作し、必要なタグ情報を取得してフロントエンドに返す役割を担います。
使用する API(2段階構成)
この構成では、Zendesk API の2つのエンドポイントを順番に呼び出す必要があります。
第1段階:記事から content_tag_ids を取得
GET /api/v2/help_center/articles/:id.json
レスポンス例(抜粋):
{
"article": {
"id": 123456789,
"title": "テンプレート:よくある質問",
"content_tag_ids": [112233, 445566]
}
}
第2段階:タグ ID からタグ名を取得
GET /api/v2/guide/content_tags/:id.json
レスポンス例:
{
"content_tag": {
"id": 112233,
"name": "jp"
}
}
Lambda 実装例
検証では AWS Lambda を Node.js 22.x で実装し、API Gateway 経由で HTTPS リクエストを受け取れるよう構成しています。トークンによる Basic 認証の処理や、非同期 API 呼び出しのハンドリングを行うだけのシンプルな設計です。
検証環境
- ランタイム : Node.js 22.x
- ライブラリ :
node-fetch@2
- 環境変数で以下を定義:
環境変数 | 用途 |
---|---|
ZENDESK_DOMAIN |
例: yourcompany.zendesk.com |
ZENDESK_EMAIL |
API 認証用メールアドレス(/token) |
ZENDESK_API_TOKEN |
Zendesk API トークン |
Lambda コード(index.js)
実装の全体像としては、リクエストパラメータから article_id
を受け取り、Zendesk の記事情報 API → タグ情報 API を順に呼び出し、タグ名のリストを JSON として返却するという処理です。以下がそのサンプルコードです。
const fetch = require("node-fetch");
const ZENDESK_DOMAIN = process.env.ZENDESK_DOMAIN;
const ZENDESK_EMAIL = process.env.ZENDESK_EMAIL;
const ZENDESK_API_TOKEN = process.env.ZENDESK_API_TOKEN;
exports.handler = async (event) => {
const articleId = event.queryStringParameters?.article_id;
if (!articleId) {
return { statusCode: 400, body: "Missing article_id" };
}
const authHeader = "Basic " + Buffer.from(`${ZENDESK_EMAIL}:${ZENDESK_API_TOKEN}`).toString("base64");
try {
const articleRes = await fetch(`https://${ZENDESK_DOMAIN}/api/v2/help_center/articles/${articleId}.json`, {
headers: { Authorization: authHeader }
});
const articleJson = await articleRes.json();
const tagIds = articleJson.article?.content_tag_ids || [];
const tagNames = await Promise.all(tagIds.map(async (id) => {
const res = await fetch(`https://${ZENDESK_DOMAIN}/api/v2/guide/content_tags/${id}.json`, {
headers: { Authorization: authHeader }
});
const json = await res.json();
return json.content_tag?.name;
}));
return {
statusCode: 200,
body: JSON.stringify({ tags: tagNames.filter(Boolean) }),
headers: { "Access-Control-Allow-Origin": "*" }
};
} catch (err) {
console.error("タグ取得失敗:", err);
return { statusCode: 500, body: JSON.stringify({ error: "Internal error" }) };
}
};
動作確認用 curl コマンド
curl -X GET \
'https://your-api-id.execute-api.ap-northeast-1.amazonaws.com/default/zendeskContentTagProxy?article_id=123456789'
レスポンス例:
{ "tags": ["jp", "beta"] }
この Lambda 関数が動作していれば、次にクライアント側で fetch()
によってこの API を呼び、DOM にタグを描画することが可能になります。
セクションテンプレートにタグを描画する JavaScript の実装
Proxy API の準備ができたら、次は section_page.hbs
から呼び出される script.js
を編集して、実際にタグを描画していきます。本構成では、各記事タイトルの横に #jp
や #beta
などのタグを表示することを目指します。
article_id
を data 属性として埋め込む
1. テンプレート側:以下のように、各 <li>
要素に data-article-id="{{id}}"
を追加しておきます。
<ul class="article-list">
<li class="article-list-item" data-article-id="">
<a href="" class="article-list-link"></a>
</li>
</ul>
2. JavaScript の実装:タグを取得して描画
セクションページが読み込まれた後、JavaScript で各記事の data-article-id
を取得し、Lambda 経由でタグ情報を取得します。取得したタグ名は DOM に挿入し、記事タイトルの直後に表示されるようにします。
document.addEventListener("DOMContentLoaded", async () => {
const items = document.querySelectorAll(".article-list-item");
for (const item of items) {
const articleId = item.getAttribute("data-article-id");
if (!articleId) continue;
try {
const res = await fetch(
`https://your-api-id.execute-api.ap-northeast-1.amazonaws.com/default/zendeskContentTagProxy?article_id=${articleId}`
);
const data = await res.json();
const tags = data.tags || [];
if (tags.length > 0) {
const tagContainer = document.createElement("span");
tagContainer.classList.add("tag-list");
tags.forEach((tag) => {
const span = document.createElement("span");
span.classList.add("tag");
span.textContent = `#${tag}`;
tagContainer.appendChild(span);
});
const link = item.querySelector(".article-list-link");
if (link) {
link.insertAdjacentElement("afterend", tagContainer);
}
}
} catch (e) {
console.error(`タグ取得失敗(article_id=${articleId}):`, e);
}
}
});
3. スタイリング(任意)
タグ表示が見やすくなるよう、以下のような簡単なスタイルを追加しておくと便利です。
.tag-list {
margin-left: 8px;
display: inline-flex;
gap: 4px;
}
.tag {
font-size: 12px;
color: #666;
background-color: #eee;
padding: 2px 6px;
border-radius: 4px;
}
4. 注意点・補足
-
fetch()
の呼び出しは記事ごとに個別実行されるため、記事数が多いと並列アクセスが発生します。- 必要に応じてキャッシュ機構や
Promise.allSettled()
を使った並列制御も検討してください。
- 必要に応じてキャッシュ機構や
-
クライアントサイドで描画されるため、JavaScript 無効時はタグが表示されません。
-
content_tags
が使用可能な料金プランについては別途ご確認ください。
まとめ
本記事では、Zendesk Guide のセクションページに記事ごとの「コンテンツタグ(content tags)」を表示する構成を紹介しました。
デフォルトのテンプレートでは content_tag_ids
が展開されないため、タグ情報を取得するには JavaScript + Zendesk API の組み合わせが不可欠です。
しかし、Zendesk API の呼び出しには認証が必要なため、クライアントから直接取得することはできません。
この制約を解決するため、AWS Lambda を用いた Proxy API を中継サーバーとして構築し、テンプレート側から非同期にタグ情報を取得して表示する方法を取りました。
本構成のポイント
要素 | 説明 |
---|---|
Lambda + API Gateway | Zendesk API を代理で呼び出す Proxy API を構築し、認証をサーバー側で管理 |
クライアント JS | section.articles の各記事 ID をもとにタグ情報を取得して DOM に描画 |
非同期処理 | JavaScript によって複数記事に対する API 呼び出しを並列処理 |
セキュリティ配慮 | CORS 対策および API 認証情報の秘匿をサーバー側で完結 |
スタイリング | タグ表示に CSS クラスを用いることで、見やすさやアクセントを追加可能 |
今後の展開・検討ポイント
- タグのクリックで絞り込みを行う構成(例:タグをクリックすると
https://support.example.com/hc/ja/sections/1234567890-FAQ?tag=jp
に遷移し、該当タグを含む記事のみを絞り込んで表示) - content_tags のキャッシュ構造の導入(記事数が多い場合の最適化)
- Proxy サーバーの運用管理・監視体制
おわりに
Zendesk Guide のカスタマイズでは、公式テンプレートの制約をうまく乗り越えていく必要があります。
今回のように、「直接取得できない情報は API 経由で補完し、描画はクライアントで行う」 というパターンは、他の用途でも応用しやすい汎用的なアプローチです。
本構成が、Zendesk カスタマイズに取り組む方の参考になれば幸いです。