GA4 / i-cherry Web dataLayer
Ownership
Record Web emits the client-approved analytics contract as plain objects in
window.dataLayer. Record owns the Google Tag Manager configuration that maps
those objects to GA4/i-cherry. The application does not load gtag.js, configure
a GA4 measurement ID, or send events directly to a GA4 property.
The contract combines Web v09 with the 2026-08-04 Accedo-layout revision
([R7+iC] Mapa de Tags GA4 - RecordPlus - Web-v1.pdf, SHA-256
30165e59acf11a720e2a7343d644046e572d3548189556665f57be4392042825).
Event shape
Non-ecommerce events use a flat dataLayer object:
globalThis.dataLayer.push({ event: 'login', method: 'email' });
Ecommerce events clear stale ecommerce state and then use the documented nested shape:
globalThis.dataLayer.push({ ecommerce: null });
globalThis.dataLayer.push({
event: 'purchase',
ecommerce: {
currency: 'BRL',
value: 30.5,
transaction_id: '...',
items: [],
},
});
Authenticated identity is dataLayer state. userId is SHA-256 of the email
after trimming and lower-casing; raw email is never pushed. plano is the active
plan title and planoid is its ID. All three values are cleared on logout.
client_id is generated by GA4 and is not sent as a custom field.
Personal data — sign-off required
userId is a pseudonymous identifier derived from the account email, so it is
still personal data under the LGPD: it is stable per user and re-identifiable by
anyone able to hash a candidate email. Hashing reduces exposure; it does not take
the value out of scope.
Before this ships to production, record here:
- Legal basis / consent — which basis covers pushing
userIdto Record-owned GTM, and whether it must be gated on a consent signal rather than emitted for every authenticated session. - Retention — how long the GA4 property keeps user-scoped data.
- Deletion path — how an LGPD erasure request reaches GA4, given the
application only writes to
dataLayerand does not own the property.
The implementation intentionally fails open: if crypto.subtle is unavailable
(any non-secure context) the hash rejects and no identity is pushed, so playback
and navigation are unaffected.
Status: unresolved — needs Record's DPO/legal confirmation.
Page views
useGA4ScreenTracking(pathname) emits one explicit page_view for each route
change. ga4ScreenPaths.ts maps the Next.js pathname to the canonical i-cherry
page_title; page_location remains the real browser URL.
Payment information
trackAddPaymentInfo implements the approved add_payment_info payload,
including payment_type, but is intentionally not connected to the current
Cleeng Hosted Widget. That API exposes checkout loaded and payment result events,
not payment-method selection. Emitting it at payment success would put the event
at the wrong funnel stage. Connect it only when the checkout provides a genuine
pre-purchase payment-method callback.
Validation
- Open browser DevTools and inspect
window.dataLayer. - Perform the mapped action and verify exactly one object with the expected
eventand parameters. - For ecommerce, verify
{ ecommerce: null }immediately precedes the event. - In GTM Preview, confirm the matching Record-owned tag fires once.
- In GA4 DebugView/Realtime, filter by the test build, device and timestamp and verify the event name and parameters. Do not use unrelated legacy-app traffic as evidence for this implementation.