L’hook page:fragments consente a un plugin di contribuire HTML grezzo, script o fogli di stile alle pagine pubbliche. È lo strumento giusto per tag di analytics, widget di terze parti, CSS personalizzato e qualsiasi altra cosa che necessiti di fornire JavaScript o markup direttamente nel browser del visitatore.
È limitato ai plugin nativi perché il suo output viene eseguito come codice first-party nel browser, al di fuori di qualsiasi confine di sandbox. Se devi solo contribuire metadati strutturati — meta tag, OpenGraph, JSON-LD, <link> rels consentiti — usa invece page:metadata, che è disponibile sia per plugin sandboxed che nativi. Vedi Hooks: page:metadata.
Capability
page:fragments richiede la capability hooks.page-fragments:register:
return definePlugin({
id: "analytics-gtm",
version: "1.0.0",
capabilities: ["hooks.page-fragments:register"],
// ...
});
La capability deve anche apparire nel descriptor.
Dove vengono renderizzati i frammenti
I template optano per ricevere frammenti includendo i componenti pertinenti da emdash/ui:
<EmDashHead />— renderizza frammenti conplacement: "head"più tutti i contributipage:metadata.<EmDashBodyStart />— renderizza frammenti conplacement: "body:start".<EmDashBodyEnd />— renderizza frammenti conplacement: "body:end".
I template che omettono uno di questi componenti ignorano silenziosamente i frammenti destinati a quel posizionamento — il tuo plugin non si rompe, i frammenti semplicemente non appaiono. Documenta il tuo requisito di posizionamento nel README del plugin.
Tipi di contributo
Un hook può restituire uno dei tre tipi di contributo:
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".
Esempi
Script esterno
Il seguente hook inietta un tag manager di terze parti in <head>:
"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,
};
},
Script inline
Il seguente hook esegue un piccolo frammento di JavaScript all’inizio di <body> sulle pagine di contenuto:
"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)};`,
};
},
Frammento HTML
Il seguente hook aggiunge un fallback noscript alla fine di <body>:
"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>`,
};
},
Frammenti multipli
Un hook può restituire un array per contribuire più frammenti contemporaneamente. Il seguente hook aggiunge sia uno script che un fallback 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>`,
},
];
},
Evento di pagina
L’hook page:fragments riceve la stessa forma di evento di 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 };
}
}
Usa event.page.kind e event.page.pageType per decidere se contribuire su una data pagina — ad esempio, saltare analytics sulle anteprime admin o iniettare JSON-LD solo sui post del blog.
Quando usare invece page:metadata
Se ciò di cui hai effettivamente bisogno è:
- Una meta description, direttiva robots o Twitter card →
page:metadataconkind: "meta". - Una proprietà OpenGraph →
page:metadataconkind: "property". - Un
<link>canonico o alternativo →page:metadataconkind: "link". - Un grafo JSON-LD →
page:metadataconkind: "jsonld".
page:metadata funziona nei plugin sandboxed, ottiene validazione e deduplicazione gratuitamente, ed evita l’onere di fiducia di fornire HTML grezzo ai visitatori. Ricorri a page:fragments solo quando devi fornire JavaScript o HTML.