@@ -29,6 +29,165 @@ All content lives in `/content`. All logic lives in `/src`. All output is static
2929
3030Content processing uses gray-matter for frontmatter parsing, remark and rehype for markdown transformation.
3131
32+ ## Tracking And Analytics
33+
34+ ### Architecture Overview
35+
36+ SIGIL.ZERO uses a browser-side tracker at ` /public/assets/js/tracking.js ` with a GTM-first pipeline.
37+
38+ - ` tracking.js ` is vendor-agnostic and only pushes normalized objects into ` window.dataLayer ` .
39+ - Google Tag Manager (GTM) is installed once in the root app shell.
40+ - GA4 and Meta are configured in GTM, not in application code.
41+ - No direct ` gtag() ` or ` fbq() ` calls exist in the app code.
42+
43+ ### GTM-First Rationale
44+
45+ This keeps analytics implementation centralized and safer to evolve:
46+
47+ - Application code emits one stable event contract.
48+ - Tag vendors are configured in GTM without redeploying app code.
49+ - Event governance, filtering, and mapping live in one place.
50+ - Privacy controls remain inside a single normalization layer.
51+
52+ ### Container Configuration
53+
54+ - GTM Container ID: ` GTM-TLP35C5T `
55+ - GA4 Measurement ID (configured in GTM): ` G-K5W8ENE0DH `
56+
57+ ### Event Schema Contract
58+
59+ All custom events must push with:
60+
61+ - ` event: "sigilzero_event" `
62+
63+ Core contract:
64+
65+ - ` entity `
66+ - ` action `
67+ - ` target `
68+
69+ Events missing any of those three required fields are blocked and not pushed.
70+
71+ ### Supported Payload Fields
72+
73+ ` tracking.js ` emits a flat payload (no arrays/objects) and allows these keys:
74+
75+ - ` event `
76+ - ` entity `
77+ - ` action `
78+ - ` target `
79+ - ` platform `
80+ - ` page_type `
81+ - ` page_path `
82+ - ` page_title `
83+ - ` release_title `
84+ - ` release_catalog_id `
85+ - ` artist_name `
86+ - ` track_title `
87+ - ` cta_type `
88+ - ` section `
89+ - ` component `
90+ - ` link_url `
91+ - ` link_text `
92+ - ` destination_domain `
93+ - ` is_external `
94+ - ` debug_source `
95+
96+ ### Debug Mode
97+
98+ Enable debug mode either way:
99+
100+ - Set local storage: ` localStorage.setItem("sigilzero_debug_tracking", "true") `
101+ - Or use URL param: ` ?debug_tracking=true `
102+
103+ When enabled, events include:
104+
105+ - ` debug_source: "tracking.js" `
106+
107+ And helper methods are available in the console:
108+
109+ - ` window.SigilZeroTracking.debugStatus() `
110+ - ` window.SigilZeroTracking.testEvent() `
111+ - ` window.SigilZeroTracking.getConsoleTestExamples() `
112+
113+ ### GTM Setup Workflow
114+
115+ 1 . Open GTM container ` GTM-TLP35C5T ` .
116+ 2 . Create a Custom Event trigger where ` Event name = sigilzero_event ` .
117+ 3 . Create Data Layer Variables for fields you need (for example ` entity ` , ` action ` , ` target ` , ` platform ` , ` page_type ` , ` link_url ` ).
118+ 4 . Attach GA4/Meta tags to the custom event trigger.
119+ 5 . Use GTM Preview to validate payload values before publishing.
120+
121+ ### GA4 Setup Workflow
122+
123+ 1 . In GTM, create a GA4 Configuration tag using measurement ID ` G-K5W8ENE0DH ` .
124+ 2 . Create a GA4 Event tag triggered by ` sigilzero_event ` .
125+ 3 . Map Data Layer Variables to GA4 event parameters.
126+ 4 . Validate in GTM Preview, then GA4 DebugView.
127+
128+ ### Meta Setup Workflow
129+
130+ 1 . Add a Meta Pixel tag in GTM (no direct pixel script in app code).
131+ 2 . Trigger from ` sigilzero_event ` (or filtered subsets).
132+ 3 . Map only approved, non-PII fields.
133+ 4 . Validate in Meta Test Events.
134+
135+ ### Embed play_intent Behavior
136+
137+ Embed interactions (Spotify/SoundCloud) push:
138+
139+ - ` entity: "embed" `
140+ - ` action: "play_intent" `
141+ - ` target: "spotify_embed" ` or ` target: "soundcloud_embed" `
142+
143+ Embed events are deduped with a longer window (` EMBED_DEDUPE_WINDOW_MS = 2000 ` ) to prevent duplicate pushes from iframe focus/blur behavior.
144+
145+ ### Privacy And PII Rules
146+
147+ ` tracking.js ` applies defensive sanitization:
148+
149+ - Blocks email-like and phone-like free-text values.
150+ - Redacts ` mailto: ` and ` tel: ` links (` link_url: "redacted" ` , ` target: "contact_link" ` ).
151+ - Blocks nested objects/arrays from payload output.
152+ - Drops undefined/null values.
153+
154+ ### URL Sanitization Rules
155+
156+ - Only ` http ` /` https ` URLs are allowed for normal tracked links.
157+ - Querystrings are stripped from ` link_url ` .
158+ - Hash fragments are stripped from ` link_url ` .
159+ - External domain extraction is preserved for external links only.
160+ - Valid commerce URLs with numeric path IDs are preserved.
161+
162+ Notes:
163+
164+ - Query parameter stripping is intentional to avoid analytics noise and accidental parameter leakage.
165+ - ` mailto: ` and ` tel: ` are never sent as raw URLs.
166+
167+ ### Local Testing Workflow
168+
169+ 1 . Run ` npm run dev ` .
170+ 2 . Open the site and DevTools console.
171+ 3 . Confirm ` window.dataLayer ` exists and receives ` sigilzero_event ` payloads.
172+ 4 . Exercise page views, release/artist/social/stream/store links, and embed interactions.
173+ 5 . Confirm payloads stay flat and contain no undefined values.
174+
175+ ### GTM Preview Testing Workflow
176+
177+ 1 . Start GTM Preview for ` GTM-TLP35C5T ` .
178+ 2 . Navigate core routes (` / ` , ` /releases ` , release detail, artist detail).
179+ 3 . Trigger representative interactions (stream/store/social/embed).
180+ 4 . Confirm each event appears as ` sigilzero_event ` .
181+ 5 . Verify mapped variables and publish after validation.
182+
183+ ### GA4 DebugView Workflow
184+
185+ 1 . Keep GTM Preview active.
186+ 2 . Open GA4 DebugView.
187+ 3 . Trigger key interactions and confirm receipt.
188+ 4 . Validate expected parameters (` entity ` , ` action ` , ` target ` , page context, link metadata).
189+ 5 . Confirm no unexpected PII-like parameter values appear.
190+
32191## Local Development
33192
34193Install dependencies:
@@ -175,4 +334,3 @@ Speed and simplicity over feature accumulation.
175334
176335- This repository’s source code is released under the MIT License.
177336- Brand identity, artwork, and site content are excluded and remain proprietary.
178-
0 commit comments