Blog · November 5, 2026 · 3 min de lectura

GA4's missing third step: a three-page flow from one event

GA4 records page transitions in pairs. A 20-line snippet that sends the previous two paths as a nav_step event shows A → B → C with real data, no cookie, no tool.

Por seops team · Türkçesi

Short answer. GA4's path exploration knows A→B and B→C but not that the people who did B came from A. Send one custom event, nav_step, with two parameters, prev_path and prev2_path, kept in sessionStorage. Register them as event-scoped custom dimensions and you can query three-step paths in GA4 or let seops draw them: hover a page on the left of the flow and only its continuation lights up.

What GA4 actually stores

GA4’s path exploration is built on page_referrer. For every page view it knows the page before it. That gives you every pair: home → pricing, pricing → docs, docs → signup. It cannot tell you whether the people who went docs → signup are the same people who came home → pricing → docs, because each page view only remembers one step back.

For most questions that’s fine. For the one question product people ask every week, “what do visitors do after they read X?”, it isn’t.

The event

Send one event on every page view, after GA4 loads:

// nav_step: previous two paths, kept per tab, no cookie
(function () {
  try {
    var S = sessionStorage, h = JSON.parse(S.getItem("nav_hist") || "[]"), c = location.pathname, r = "";
    try { var u = new URL(document.referrer); if (u.host === location.host) r = u.pathname; } catch (e) {}
    if (h[h.length - 1] === c) return; // reload
    if (r && r !== c) {
      var p = { prev_path: r.slice(0, 100), prev2_path: (h[h.length - 1] === r ? h[h.length - 2] || "(entry)" : "(unknown)").slice(0, 100) };
      if (window.zaraz && zaraz.track) zaraz.track("nav_step", p); else if (window.gtag) gtag("event", "nav_step", p);
    }
    S.setItem("nav_hist", JSON.stringify(r ? [r, c] : [c]));
  } catch (e) {}
})();

Two parameters: prev_path (the page before this one) and prev2_path (the page before that). The history lives in sessionStorage under one key and is overwritten on every navigation, so the storage never grows past two entries.

Registering the dimensions

GA4 ignores parameters it doesn’t know about. In Admin → Data display → Custom definitions create two event-scoped custom dimensions:

Dimension nameScopeEvent parameter
Previous pageEventprev_path
Page before previousEventprev2_path

Dimensions only cover data from the day they were created, so do this first.

If you use Zaraz

Cloudflare Zaraz doesn’t forward unknown zaraz.track events automatically. Under Zaraz → Tools → Google Analytics 4 → Actions add an action with trigger {{ client.__zarazTrack }} equals nav_step, event name nav_step, and two fields: prev_path = {{ client.prev_path }}, prev2_path = {{ client.prev2_path }}.

Reading it

In GA4: Explore → Free form, dimension Page path with Previous page and Page before previous, metric Event count, filter event name = nav_step. Each row is a three-step path with its count.

In seops: Tracking › Traffic › Navigation, then the flow. Pick a page; the flow shows where its visitors came from (left) and went next (right). Hover a page on the left and only the paths that continue from it stay lit; that is the third step. Your assistant can read the same table with get_navigation.

Three things we learned running it

  1. “(unknown)” is bigger than you think. On content sites 20–30% of page views start in a new tab. That is not noise; it tells you how people use your site.
  2. Entry → page → exit is the most useful triple. It separates pages that end journeys because they answered the question from pages that end journeys because they failed.
  3. The data arrives in a day, not two or three like Search Console. Realtime shows the event within seconds; the flow in seops fills by the next morning.

Preguntas

Doesn't this add a cookie?

No. The snippet uses sessionStorage, which lives in one tab and is deleted when it closes. Nothing is sent to a third party except the GA4 event you already send.

Why only two previous pages?

Two is enough to answer 'where did people who came from the pricing page go after reading the docs?'. Three or more multiplies cardinality and GA4 starts sampling and bucketing the dimension values.

What is (unknown)?

The visitor opened the page in a new tab, so that tab has no history. (entry) means the previous page was the landing page.

Empieza gratis con un sitio

El primer sitio es gratis para siempre y sin tarjeta. Cada sitio adicional cuesta 2,50 $ al mes.