@hubpav/hwio-web-runtime 0.7.10 → 0.8.0
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.
- package/dist/attribution.d.ts +9 -1
- package/dist/attribution.js +27 -3
- package/dist/forms.js +4 -2
- package/package.json +1 -1
package/dist/attribution.d.ts
CHANGED
|
@@ -2,12 +2,20 @@ export declare const HWIO_ATTRIBUTION_KEY = "hwio_attribution";
|
|
|
2
2
|
/** Click identifiers + UTM params; lowercase keys map onto HubSpot contact properties of the same name. */
|
|
3
3
|
export declare const HWIO_ATTRIBUTION_PARAMS: readonly ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content", "gclid", "gbraid", "wbraid", "fbclid", "msclkid", "li_fat_id"];
|
|
4
4
|
export type HWioAttribution = Record<string, string>;
|
|
5
|
-
/** Pure: click identifiers present in a query string
|
|
5
|
+
/** Pure: click identifiers present in a query string. */
|
|
6
6
|
export declare function hwioAttributionFromSearch(search: string): HWioAttribution;
|
|
7
|
+
/** Pure: first value per key wins, in the order the sources are given (earliest touch first). */
|
|
8
|
+
export declare function hwioFirstTouch(...sources: (HWioAttribution | undefined)[]): HWioAttribution;
|
|
9
|
+
/**
|
|
10
|
+
* Remembers the current URL's click ids and UTM parameters in memory (first touch). Call on every
|
|
11
|
+
* page load; the forms runtime does. No consent is needed because nothing is stored or sent.
|
|
12
|
+
*/
|
|
13
|
+
export declare function hwioRememberLandingAttribution(): void;
|
|
7
14
|
/**
|
|
8
15
|
* First-touch capture into sessionStorage (marketing storage: call only with marketing consent).
|
|
9
16
|
* Keeps the first value seen in the session so later navigations cannot clobber the campaign.
|
|
10
17
|
*/
|
|
11
18
|
export declare function hwioCaptureAttribution(): void;
|
|
12
19
|
export declare function hwioGetAttribution(): HWioAttribution;
|
|
20
|
+
/** Click ids and UTM parameters of this visit: the remembered landing values, then the current URL. */
|
|
13
21
|
export declare function hwioGetPageAttribution(): HWioAttribution;
|
package/dist/attribution.js
CHANGED
|
@@ -3,7 +3,7 @@ const LEGACY_ATTRIBUTION_KEY = 'hw_attribution'; // legacy-ok
|
|
|
3
3
|
const MAX_LEN = 512;
|
|
4
4
|
/** Click identifiers + UTM params; lowercase keys map onto HubSpot contact properties of the same name. */
|
|
5
5
|
export const HWIO_ATTRIBUTION_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid', 'gbraid', 'wbraid', 'fbclid', 'msclkid', 'li_fat_id'];
|
|
6
|
-
/** Pure: click identifiers present in a query string
|
|
6
|
+
/** Pure: click identifiers present in a query string. */
|
|
7
7
|
export function hwioAttributionFromSearch(search) {
|
|
8
8
|
const out = {};
|
|
9
9
|
const params = new URLSearchParams(search);
|
|
@@ -14,6 +14,28 @@ export function hwioAttributionFromSearch(search) {
|
|
|
14
14
|
}
|
|
15
15
|
return out;
|
|
16
16
|
}
|
|
17
|
+
/** Pure: first value per key wins, in the order the sources are given (earliest touch first). */
|
|
18
|
+
export function hwioFirstTouch(...sources) {
|
|
19
|
+
const out = {};
|
|
20
|
+
for (const source of sources) {
|
|
21
|
+
for (const [key, value] of Object.entries(source ?? {}))
|
|
22
|
+
if (value && !out[key])
|
|
23
|
+
out[key] = value;
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
// The landing page's click ids and UTM parameters, held in memory only: nothing is written to the
|
|
28
|
+
// device, and nothing leaves the browser unless a form is sent with marketing consent. The memory
|
|
29
|
+
// lives as long as the page's JavaScript does, so it survives Astro ClientRouter navigations
|
|
30
|
+
// (which drop the query string) and is gone after a full page load.
|
|
31
|
+
let landing;
|
|
32
|
+
/**
|
|
33
|
+
* Remembers the current URL's click ids and UTM parameters in memory (first touch). Call on every
|
|
34
|
+
* page load; the forms runtime does. No consent is needed because nothing is stored or sent.
|
|
35
|
+
*/
|
|
36
|
+
export function hwioRememberLandingAttribution() {
|
|
37
|
+
landing = hwioFirstTouch(landing, hwioAttributionFromSearch(window.location.search));
|
|
38
|
+
}
|
|
17
39
|
function read() {
|
|
18
40
|
try {
|
|
19
41
|
const raw = sessionStorage.getItem(HWIO_ATTRIBUTION_KEY) ?? sessionStorage.getItem(LEGACY_ATTRIBUTION_KEY);
|
|
@@ -30,7 +52,8 @@ function read() {
|
|
|
30
52
|
export function hwioCaptureAttribution() {
|
|
31
53
|
const stored = read();
|
|
32
54
|
let changed = false;
|
|
33
|
-
|
|
55
|
+
// The remembered landing values first: consent given on a later page keeps the ad click.
|
|
56
|
+
for (const [key, value] of Object.entries(hwioGetPageAttribution())) {
|
|
34
57
|
if (!stored[key]) {
|
|
35
58
|
stored[key] = value;
|
|
36
59
|
changed = true;
|
|
@@ -60,6 +83,7 @@ export function hwioCaptureAttribution() {
|
|
|
60
83
|
export function hwioGetAttribution() {
|
|
61
84
|
return read();
|
|
62
85
|
}
|
|
86
|
+
/** Click ids and UTM parameters of this visit: the remembered landing values, then the current URL. */
|
|
63
87
|
export function hwioGetPageAttribution() {
|
|
64
|
-
return hwioAttributionFromSearch(window.location.search);
|
|
88
|
+
return hwioFirstTouch(landing, hwioAttributionFromSearch(window.location.search));
|
|
65
89
|
}
|
package/dist/forms.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { hwioMount } from './mount.js';
|
|
2
|
-
import { hwioGetAttribution, hwioGetPageAttribution } from './attribution.js';
|
|
2
|
+
import { hwioGetAttribution, hwioGetPageAttribution, hwioRememberLandingAttribution } from './attribution.js';
|
|
3
3
|
import { hwioBuildSubmitPayload, hwioFoldMessageContext, hwioFormEventPayload, hwioGaClientId, hwioPageUri, hwioSubmitAttribution } from './forms-core.js';
|
|
4
4
|
import { hwioEnsureTurnstileToken, hwioResetTurnstile } from './turnstile.js';
|
|
5
5
|
/**
|
|
@@ -9,7 +9,8 @@ import { hwioEnsureTurnstileToken, hwioResetTurnstile } from './turnstile.js';
|
|
|
9
9
|
* data-hs-sending-msg data-hs-success-msg data-hs-error-msg data-form-kind data-inquiry-source>
|
|
10
10
|
* inside: [data-hs-status] element, optional .cf-turnstile, optional [data-message-field data-message-label] controls.
|
|
11
11
|
* `data-hs-enrich="true"` sends the HubSpot cookie, the stored attribution and the GA4 client id,
|
|
12
|
-
* each gated on the matching consent category. Click ids and UTM parameters
|
|
12
|
+
* each gated on the matching consent category. Click ids and UTM parameters of the visit (the
|
|
13
|
+
* landing page's, remembered in memory across ClientRouter navigations, then the current URL's)
|
|
13
14
|
* are sent on every form, but only with marketing consent (owner decision 2026-10-08).
|
|
14
15
|
*/
|
|
15
16
|
async function readHubspotCookie() {
|
|
@@ -80,6 +81,7 @@ function pushFormEvent(form) {
|
|
|
80
81
|
}
|
|
81
82
|
export function hwioFormsRuntime() {
|
|
82
83
|
function bind() {
|
|
84
|
+
hwioRememberLandingAttribution();
|
|
83
85
|
document.querySelectorAll('form[data-hs-form]').forEach((form) => {
|
|
84
86
|
if (form.dataset.hsBound === 'true')
|
|
85
87
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubpav/hwio-web-runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Framework-free browser runtime for the HARDWARIO websites: consent (Consent Mode v2 + GTM), HubSpot forms with Turnstile, attribution, theme, CTA tracking and small behaviours. View-transition safe.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|