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 | 7x 7x 4x 4x 45x 45x | // First-touch attribution on www (#1085). The shared helper does the work;
// this wraps the `sessionStorage` global, whose mere access throws a
// SecurityError when site data is blocked — a form must work regardless.
//
// `captureLanding()` runs once per full page load from _LayoutHead.astro (and
// from landing/get-matched.astro, which has its own <head>). It must run
// before the calculator's history.replaceState strips the UTMs from the URL.
import {
type Attribution,
captureFirstTouch,
readFirstTouch,
} from "@interioring/utils/analytics/attribution";
export function captureLanding(): void {
try {
captureFirstTouch(sessionStorage, location.search);
} catch {
// No storage, no attribution — never a broken page.
}
}
/**
* Rewrite this page's query string without losing its landing attribution.
*
* The calculator rewrites its URL 300 ms after it hydrates. `captureLanding()`
* is a module script, and on a slow or cold load it can run after that, by
* which time the UTMs are gone: 2 of 11 cold loads in #1085 QA stored nothing.
* Capturing here first makes the order irrelevant. First touch still wins, so
* when the head script already ran this capture is a no-op.
*/
export function replaceQueryKeepingFirstTouch(query: string): void {
captureLanding();
history.replaceState(null, "", `${location.pathname}?${query}`);
}
/** What this session's first landing carried, for a lead form's payload. */
export function firstTouch(): Attribution {
try {
return readFirstTouch(sessionStorage);
} catch {
return {};
}
}
|