page:fragments フックを使用すると、プラグインは公開ページに生の HTML、スクリプト、またはスタイルシートを提供できます。これは、アナリティクスタグ、サードパーティウィジェット、カスタム CSS、およびその他の JavaScript やマークアップを訪問者のブラウザに直接配信する必要があるものに適したツールです。
その出力がブラウザ内でファーストパーティコードとして実行され、サンドボックス境界の外にあるため、ネイティブプラグインに制限されています。構造化メタデータ(meta タグ、OpenGraph、JSON-LD、許可リストの <link> rels)のみを提供する必要がある場合は、サンドボックスプラグインとネイティブプラグインの両方で使用できる page:metadata を使用してください。Hooks: page:metadata を参照してください。
機能
page:fragments には hooks.page-fragments:register 機能が必要です:
return definePlugin({
id: "analytics-gtm",
version: "1.0.0",
capabilities: ["hooks.page-fragments:register"],
// ...
});
この機能はディスクリプタにも記載する必要があります。
フラグメントのレンダリング場所
テンプレートは、emdash/ui から関連するコンポーネントを含めることで、フラグメントの受信を選択します:
<EmDashHead />—placement: "head"のフラグメントとすべてのpage:metadataの貢献をレンダリングします。<EmDashBodyStart />—placement: "body:start"のフラグメントをレンダリングします。<EmDashBodyEnd />—placement: "body:end"のフラグメントをレンダリングします。
これらのコンポーネントのいずれかを省略したテンプレートは、その配置を対象とするフラグメントを静かに無視します — プラグインは壊れず、フラグメントが表示されないだけです。プラグインの README に配置要件を記載してください。
貢献の種類
3種類の貢献があります:
type PageFragmentContribution =
| {
kind: "external-script";
placement: PagePlacement;
src: string;
async?: boolean;
defer?: boolean;
attributes?: Record<string, string>;
key?: string;
}
| {
kind: "inline-script";
placement: PagePlacement;
code: string;
attributes?: Record<string, string>;
key?: string;
}
| {
kind: "html";
placement: PagePlacement;
html: string;
key?: string;
};
PagePlacement は "head" | "body:start" | "body:end" です。
例
外部スクリプト
サードパーティのタグマネージャーを注入する:
"page:fragments": async (event, ctx) => {
const containerId = await ctx.kv.get<string>("settings:gtmContainerId");
if (!containerId) return null;
return {
kind: "external-script",
placement: "head",
src: `https://www.googletagmanager.com/gtm.js?id=${containerId}`,
async: true,
};
},
インラインスクリプト
<body> の上部で小さな JavaScript を実行する:
"page:fragments": async (event, ctx) => {
if (event.page.kind !== "content") return null;
return {
kind: "inline-script",
placement: "body:start",
code: `window.contentId = ${JSON.stringify(event.page.content?.id)};`,
};
},
HTML フラグメント
<body> の末尾に noscript フォールバックを追加する:
"page:fragments": async (event, ctx) => {
const containerId = await ctx.kv.get<string>("settings:gtmContainerId");
if (!containerId) return null;
return {
kind: "html",
placement: "body:end",
html: `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${containerId}" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>`,
};
},
複数のフラグメント
単一のフックから配列を返して複数のフラグメントを提供する:
"page:fragments": async (event, ctx) => {
const id = await ctx.kv.get<string>("settings:gtmContainerId");
if (!id) return null;
return [
{
kind: "external-script",
placement: "head",
src: `https://www.googletagmanager.com/gtm.js?id=${id}`,
async: true,
},
{
kind: "html",
placement: "body:end",
html: `<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=${id}" height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>`,
},
];
},
ページイベント
page:fragments フックは page:metadata と同じイベント形状を受け取ります:
{
page: {
url: string;
path: string;
locale: string | null;
kind: "content" | "custom";
pageType: string;
title: string | null;
pageTitle?: string | null;
description: string | null;
canonical: string | null;
image: string | null;
content?: { collection: string; id: string; slug: string | null };
}
}
event.page.kind と event.page.pageType を使用して、特定のページで貢献するかどうかを決定します — たとえば、管理プレビューでアナリティクスをスキップしたり、ブログ投稿にのみ JSON-LD を注入したりします。
page:metadata を代わりに使用する場合
実際に必要なものが以下の場合:
- メタ説明、robots ディレクティブ、または Twitter カード →
page:metadataをkind: "meta"で使用します。 - OpenGraph プロパティ →
page:metadataをkind: "property"で使用します。 - canonical または alternate
<link>→page:metadataをkind: "link"で使用します。 - JSON-LD グラフ →
page:metadataをkind: "jsonld"で使用します。
page:metadata はサンドボックスプラグインで機能し、検証と重複排除が無料で提供され、訪問者に生の HTML を配信する信頼の負担を回避できます。JavaScript または HTML を本当に配信する必要がある場合にのみ page:fragments を使用してください。