Funnel analytics (GTM & dataLayer)

The public funnel (renderer) exposes a single window.dataLayer queue and named event values you can use in Google Tag Manager (Custom Event triggers). Preview mode does not load GTM, GA4, Meta Pixel, or push client analytics.

Modes (Funnel Settings)

ModeBehavior
OffNo analytics scripts on the live funnel.
Quick setupLoads gtag.js and/or Meta Pixel (only what you configure). Enabled funnel events are sent to Google / Facebook normally. The same events are also pushed to window.dataLayer for GTM — you can ignore dataLayer if you only use Pixel or only GA4.
Google Tag ManagerInjects the GTM container only; configure GA4/Pixel inside GTM.
GTM + direct IDsContainer and direct tags. The app turns off automatic GA4 page_view on the direct gtag config and does not fire Meta PageView from the direct Pixel snippet — assuming you will fire page views (and optionally Pixel) from GTM. If your container does not include a Meta Pixel tag yet, you will not see Meta page views until you add one or switch to Quick setup.

Email addresses are never pushed to dataLayer. The user_email_collected event only carries non-PII flags (for example whether a name field was present).

Quick setup: GA4 vs Meta (direct tags)

When GA4 is set, every enabled funnel event is also sent to GA4 as a custom event (same name as in the table below). When Meta Pixel is set, only three funnel events map to Meta standard events: Email captureLead, Checkout screenInitiateCheckout, Purchase completedPurchase. Other events still go to dataLayer (and to GA4 if configured), but not to Meta’s fbq API.

dataLayer contract (v1)

Every push includes:

  • event — Custom Event name for GTM (snake_case).
  • funnel_id, funnel_slug, session_id — stable for the browser session (same idea as server-side tracking).
  • UTM parameters when present in the URL (utm_source, utm_medium, etc.).

Events

eventWhen
funnel_startedFirst time the funnel is shown in this session (per funnel).
step_viewedEach step shown (including the first).
step_completedInternal continue: landing CTA, quiz answer → next, paywall continue.
user_email_collectedSuccessful email capture (no raw email in the payload).
checkout_presentedNot a purchase. Checkout screen is shown (Stripe Payment Element mounted, or Paddle pay flow ready). Maps to Meta InitiateCheckout in Quick setup.
purchase_completedPurchase / conversion on the client after returning from payment: success step URL includes _w2a_purchase=1 (we add it when building the return URL from checkout) and/or Stripe adds redirect_status=succeeded. That parameter is only a signal for analytics — the event name is purchase_completed. Server-side payment confirmation is a separate topic.

Extra fields may include step_id, step_type, step_index, processor (stripe / paddle), plan_id, has_name, etc.

GTM setup tips

  1. Create a Custom Event trigger and set the event name to match the table (e.g. purchase_completed).
  2. Use Data Layer variables to read funnel_slug, session_id, or UTM fields.
  3. If you use Quick setup or GTM + direct IDs, align Meta standard events with your pixel strategy (the app maps some events to Lead, InitiateCheckout, Purchase).

Common questions

Checkout vs success — two different things?
Yes. checkout_presented = user reached the pay screen. purchase_completed = user landed on the success step after a redirect that indicates checkout finished (our ?_w2a_purchase=1 marker or Stripe’s redirect_status). The query param is not “the purchase event”; it triggers firing purchase_completed once.

“Both” mode: why no automatic Meta PageView?
To avoid counting the same page twice when GTM might already load the Pixel and send PageView. We skip the Pixel’s automatic PageView only in GTM + direct IDs mode — if you rely on GTM for Pixel, you should have a PageView there. If you don’t, add a Pixel tag in GTM or use Quick setup.

Related