@tokenoftrust/storefront-runner 2.2.80 → 2.2.81

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,7 +19,7 @@ export const STATIC_SCRIPT_HASHES: readonly string[] = [
19
19
  "'sha256-YicfxUFBkKrQapZ/tzZKlaKTdNHgwVfv7y2Wa0NC6/k='",
20
20
  "'sha256-eIXWvAmxkr251LJZkjniEK5LcPF3NkapbJepohwYRIc='",
21
21
  "'sha256-elMLh/6Oubj8u9FRLwZLyRa6TqKikGs75mf0jfWcoxI='",
22
- "'sha256-ZxqYN/PbpT0W68E87+IwdGfcYJuAVXNPNVxVb3VX0hw='",
22
+ "'sha256-bANHtvoDkw4GnpBynM5Ib1cxdoDeNsGkPhPnDEphW3Y='",
23
23
  ];
24
24
 
25
25
  export const STATIC_STYLE_HASHES: readonly string[] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/storefront-runner",
3
- "version": "2.2.80",
3
+ "version": "2.2.81",
4
4
  "license": "SEE LICENSE IN LICENSE",
5
5
  "description": "World-shareable storefront runner: multi-tenant renderer on Astro/Cloudflare. No control plane.",
6
6
  "packageManager": "pnpm@11.9.0",
@@ -154,6 +154,18 @@ function seedSessionCookies(jar: Map<string, string>, ids: readonly string[], vi
154
154
  }
155
155
  }
156
156
 
157
+ /**
158
+ * gtag's enhanced measurement runs inside this frame and reports the frame's own
159
+ * document: its URL, its title, and a `scroll` at 90% depth that a short hidden
160
+ * document reaches on load (measured 2026-10-06 on a live stream). A frame taller than
161
+ * any viewport never reaches that depth, so the fabricated scroll is never sent.
162
+ * Setting height through the CSSOM is outside the frame's style CSP, which governs markup.
163
+ */
164
+ function suppressFrameScroll(doc: Document): void {
165
+ const root = doc.documentElement as HTMLElement | null | undefined;
166
+ if (root?.style) root.style.height = "1000000px";
167
+ }
168
+
157
169
  function validCampaign(value: unknown): value is Record<string, string> {
158
170
  const record = plainRecord(value);
159
171
  if (!record || !exactKeys(record, ["source", "medium", "campaign", "term", "content"], [])) return false;
@@ -257,6 +269,7 @@ function runPort(port: MessagePort, win: NativeGa4SandboxRuntimeWindow, doc: Doc
257
269
  });
258
270
  }
259
271
  if (doc.querySelector('script[data-tot-ga4="1"]') === null) {
272
+ suppressFrameScroll(doc);
260
273
  const script = doc.createElement("script");
261
274
  script.async = true;
262
275
  script.src = `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(ids[0]!)}`;
@@ -274,6 +287,10 @@ function runPort(port: MessagePort, win: NativeGa4SandboxRuntimeWindow, doc: Doc
274
287
  if (message["campaign"] !== undefined && !validCampaign(message["campaign"])) return;
275
288
  const pageLocation = `${canonicalOrigin}${message["path"]}`;
276
289
  lastPageLocation = pageLocation;
290
+ // Events gtag collects on its own (engagement, enhanced measurement) take the page
291
+ // from these defaults, not from the frame. The title crosses the boundary as the path:
292
+ // the frame's own title would label every page "Analytics transport".
293
+ gtag("set", { page_location: pageLocation, page_title: message["path"] });
277
294
  const params: Record<string, unknown> = {
278
295
  ...governedProperties,
279
296
  page_location: pageLocation,