[ENG-37390] feat: signals-proxy edge function and cross-domain identity cookies#3512
Open
HerbertJulio wants to merge 2 commits intodevfrom
Open
[ENG-37390] feat: signals-proxy edge function and cross-domain identity cookies#3512HerbertJulio wants to merge 2 commits intodevfrom
HerbertJulio wants to merge 2 commits intodevfrom
Conversation
Replaces @analytics/segment + analytics SDKs with a fetch-based client posting to /signals/{e,i,p}, proxied server-side by an edge function that forwards to the upstream vendor with the write key injected via Azion.env.get('SIGNALS_WRITE_KEY'). Bundle stays clean of secrets and adblockers no longer match by substring.
Cross-domain identity is shared with the marketing site through cookies under Domain=.azion.com (azion_anonymous_id and azion_user_id) so events fired before login are stitched to the userId in Segment's Identity Graph once the user authenticates.
Highlights: edge function validates payloads, sanitises userId, injects real IP from edge metadata, AbortController timeout, structured JSON logging. cookies.js with crypto.randomUUID and in-memory fallback when cookies are blocked. fetch wrapper with keepalive and silent network failures. useTracker() composable plus getTracker() singleton. Defensive guards so any tracking failure logs and degrades silently without breaking UX.
Tightens the signals/tracking modules per code review without changing public behaviour: factor invalid-userId checks into a centralised pattern array (drop the email rule which only made sense for the marketing site), simplify env var access via globalThis, replace verbose if/else logging with console[method], use Public Suffix List for cookie domain resolution with an allowlist, harden the operations behind defensive try/catch and an in-memory fallback when cookies are blocked, drop the unused #hasAnalytics indirection in the adapter and extract APPLICATION_TRAIT, and re-add the install-path guard in the plugin so analytics can never abort the Vue boot.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces the legacy Segment SDKs with a fetch-based analytics client that posts to a same-origin proxy (
/signals/{e,i,p}), forwarded by an Azion edge function to the upstream telemetry vendor with the write key injected server-side viaAzion.env.get('SIGNALS_WRITE_KEY'). Adblockers no longer match by substring, the bundle no longer ships the write key, and identity is shared with the marketing site through cookies underDomain=.azion.com.Root cause
api.segment.io, which uBlock/Pi-hole/AdGuard block by domain.VITE_SEGMENT_TOKEN(any visitor could read it).azion.comandconsole.azion.comlived in separate cookies, so a visitor that completed signup lost their pre-auth attribution in Segment's Identity Graph.Changes
Edge / config
edge-functions/signals-proxy.js(new): handles/signals/{e,i,p}, validates payloads, sanitisesuserId(rejects email /anon_*/undefined), pulls real client IP fromrequest.metadata.remote_addr, forwards with a 5sAbortControllertimeout, structured JSON logging.azion.config.mjs: declares thesignals-proxyfunction, adds the^/signals/(e|i|p)$rule before the catch-all/apiroute, excludes^/signals/fromindex.htmlrewrites and cache-control headers.Identity / cookies
src/utils/cookies.js(new):getAzionAnonymousId,resetAzionAnonymousId,getAzionUserId,setAzionUserId,clearAzionUserId. Cookies live under.azion.com, withcrypto.randomUUID()for fresh anonymous ids and an in-memory singleton fallback when cookies are blocked.Client / wiring
src/plugins/factories/analytics-tracking-factory.js: rewrite — fetch wrapper withkeepalive: true, silent network failures, no SDK.src/plugins/AnalyticsTrackerAdapterPlugin.js: exposesgetTracker()singleton +provide('tracker', ...). Plugin install fails safely (no-op adapter) if tracker construction throws.src/composables/useTracker.js(new):useTracker()for components; falls back togetTracker()outside of component context.src/plugins/analytics/AnalyticsTrackerAdapter.js: defensive try/catch wrappingtrack,identify,reset. Public API preserved — no consumer changes.src/plugins/factories/segment-handler-token-factory.jsand its test: deleted.package.json/yarn.lock:@analytics/segmentandanalyticsremoved; no new dependencies.Operational follow-up
SIGNALS_WRITE_KEYin the Azion Console (Account → Environment Variables) for prod and stage. Without it, the edge function returns 500.cookie.domain='.azion.com'on the Segment SDK init and readazion_user_idon boot to callidentify(userId)automatically. Tracked separately.fix: hubspot tracking) also createssrc/utils/cookies.js. When it merges, rebase this branch and concatenate the two function families (Azion identity + HubSpot helpers) — namespaces are distinct, no logical conflict.Test plan
yarn test:unit:headless— 1196 passed, 5 skipped (no failures introduced)yarn installsyncs lockfile without legacy SDKscurl -i https://stage-console.azion.com/signals/e -H 'Content-Type: application/json' -d '{"anonymousId":"smoke","event":"smoke"}'→ 200{"status":"sent"}onceSIGNALS_WRITE_KEYis registeredconsole.azion.com/signals/...requests, zero*.segment.*azion_anonymous_idpresent under.azion.com; logout regenerates it; account switch preserves itcontext.ippopulated from edge metadata (not127.0.0.1or edge IP)