Skip to main content

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 userId to 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 dataLayer and 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

  1. Open browser DevTools and inspect window.dataLayer.
  2. Perform the mapped action and verify exactly one object with the expected event and parameters.
  3. For ecommerce, verify { ecommerce: null } immediately precedes the event.
  4. In GTM Preview, confirm the matching Record-owned tag fires once.
  5. 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.