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, Drittanbieter-Widgets, benutzerdefiniertes CSS und alles andere, das JavaScript oder Markup direkt in den Browser des Besuchers liefern muss.

Es ist auf native Plugins beschränkt, da seine Ausgabe als First-Party-Code im Browser läuft, 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 sandboxed als auch für native Plugins verfügbar ist. Siehe Hooks: page:metadata.

Capability

page:fragments erfordert die hooks.page-fragments:register Capability:

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

Die Capability muss auch im Descriptor erscheinen.

Wo Fragmente gerendert werden

Templates können Fragmente empfangen, 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".

Templates, 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 Platzierungsanforderung in der README des Plugins.

Contribution-Arten

Ein Hook kann eine von drei Contribution-Arten zurückgeben:

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

Der folgende Hook fügt einen Drittanbieter-Tag-Manager in <head> ein:

"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

Der folgende Hook führt ein kleines JavaScript-Stück oben im <body> auf Content-Seiten aus:

"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

Der folgende Hook fügt ein noscript-Fallback am Ende von <body> hinzu:

"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 Hook kann ein Array zurückgeben, um mehrere Fragmente auf einmal beizutragen. Der folgende Hook fügt sowohl ein Skript als auch ein noscript-Fallback hinzu:

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

Der page:fragments Hook erhält dieselbe Event-Form 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 Blog-Posts einfügen.

Wann stattdessen page:metadata verwenden

Wenn Sie tatsächlich benötigen:

  • Eine Meta-Beschreibung, Robots-Direktive oder Twitter-Card → page:metadata mit kind: "meta".
  • Eine OpenGraph-Eigenschaft → page:metadata mit kind: "property".
  • Einen kanonischen oder alternativen <link>page:metadata mit kind: "link".
  • Einen JSON-LD-Graph → page:metadata mit kind: "jsonld".

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