Seitenfragmente

Auf dieser Seite

Der page:fragments-Hook ermöglicht es einem Plugin, rohes HTML, Skripte oder Stylesheets zu öffentlichen Seiten beizutragen. Es ist das richtige Werkzeug für Analytics-Tags, Widgets von Drittanbietern, benutzerdefiniertes CSS und alles andere, was JavaScript oder Markup direkt in den Browser des Besuchers liefern muss.

Er ist auf native Plugins beschränkt, da seine Ausgabe als First-Party-Code im Browser ausgeführt wird, außerhalb jeglicher Sandbox-Grenzen. Wenn Sie nur strukturierte Metadaten beitragen müssen — Meta-Tags, OpenGraph, JSON-LD, zugelassene <link>-Rels — verwenden Sie stattdessen page:metadata, das sowohl für Sandbox- als auch für native Plugins verfügbar ist. Siehe Hooks: page:metadata.

Fähigkeit

page:fragments erfordert die Fähigkeit hooks.page-fragments:register:

return definePlugin({
	id: "analytics-gtm",
	version: "1.0.0",
	capabilities: ["hooks.page-fragments:register"],
	// ...
});

Die Fähigkeit muss auch im Deskriptor erscheinen.

Wo Fragmente gerendert werden

Vorlagen entscheiden sich für den Empfang von Fragmenten, indem sie die relevanten Komponenten aus emdash/ui einbinden:

  • <EmDashHead /> — rendert Fragmente mit placement: "head" plus alle page:metadata-Beiträge.
  • <EmDashBodyStart /> — rendert Fragmente mit placement: "body:start".
  • <EmDashBodyEnd /> — rendert Fragmente mit placement: "body:end".

Vorlagen, die eine dieser Komponenten weglassen, ignorieren stillschweigend Fragmente, die auf diese Platzierung abzielen — Ihr Plugin bricht nicht, die Fragmente erscheinen einfach nicht. Dokumentieren Sie Ihre Platzierungsanforderungen in der README des Plugins.

Beitragsarten

Drei Arten von Beiträgen:

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 ist "head" | "body:start" | "body:end".

Beispiele

Externes Skript

Einen Drittanbieter-Tag-Manager einfügen:

"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,
	};
},

Inline-Skript

Ein kleines Stück JavaScript oben in <body> ausführen:

"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-Fragment

Ein Noscript-Fallback am Ende von <body> anhängen:

"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>`,
	};
},

Mehrere Fragmente

Ein Array zurückgeben, um mehrere Fragmente von einem einzigen Hook beizutragen:

"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>`,
		},
	];
},

Seitenereignis

Der page:fragments-Hook empfängt die gleiche Ereignisform wie 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 };
	}
}

Verwenden Sie event.page.kind und event.page.pageType, um zu entscheiden, ob Sie auf einer bestimmten Seite beitragen möchten — zum Beispiel Analytics bei Admin-Vorschauen überspringen oder JSON-LD nur bei Blogbeiträgen einfügen.

Wann stattdessen page:metadata verwenden

Wenn das, was Sie tatsächlich benötigen, Folgendes ist:

  • Eine Meta-Beschreibung, Robots-Direktive oder Twitter-Karte → page:metadata mit kind: "meta".
  • Eine OpenGraph-Eigenschaft → page:metadata mit kind: "property".
  • Ein kanonischer oder alternativer <link>page:metadata mit kind: "link".
  • Ein JSON-LD-Graph → page:metadata mit kind: "jsonld".

page:metadata funktioniert in Sandbox-Plugins, erhält kostenlos Validierung und Deduplizierung und vermeidet die Vertrauenslast, rohes HTML an Besucher zu liefern. Greifen Sie nur dann auf page:fragments zurück, wenn Sie wirklich JavaScript oder HTML liefern müssen.