All files / src/scripts gtm-spa.ts

100% Statements 4/4
100% Branches 2/2
100% Functions 1/1
100% Lines 4/4

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46                                                                  1x 6x 6x           6x        
// SPA page-view bridge for GTM.
//
// Astro's ClientRouter (view transitions) does not trigger GTM's History
// Change trigger reliably, so we push a custom `virtualPageview` event after
// every same-origin nav. In GTM, configure a GA4 Event tag (event_name:
// page_view) on Custom Event trigger = `virtualPageview`.
//
// We listen on `astro:after-swap` rather than `astro:page-load` because
// `after-swap` fires ONLY on view-transition navs (not on the initial page
// load). The GA4 Configuration tag handles the initial page_view via its
// built-in automatic page_view setting — listening to `page-load` here would
// double-count first-load views.
 
// `dataLayer` is a shared global owned by GTM. Other tags (GA4 init, GTM
// internal events, ad pixels, custom user pushes) push objects of arbitrary
// shapes. Type the global permissively so foreign pushes typecheck, while
// keeping our own virtualPageview push narrowly typed at the call site.
// Type alias (not interface) so it satisfies the open `Record<string, unknown>`
// index signature of `Window.dataLayer` — TS treats interfaces as
// closed shapes that don't widen to index signatures.
type VirtualPageviewEvent = {
	event: "virtualPageview";
	page_path: string;
	page_title: string;
	page_location: string;
};
 
declare global {
	interface Window {
		dataLayer?: Array<Record<string, unknown>>;
	}
}
 
document.addEventListener("astro:after-swap", () => {
	window.dataLayer = window.dataLayer ?? [];
	const event: VirtualPageviewEvent = {
		event: "virtualPageview",
		page_path: window.location.pathname + window.location.search,
		page_title: document.title,
		page_location: window.location.href,
	};
	window.dataLayer.push(event);
});
 
export {};