Laravel tracking

Laravel Conversion Tracking: GA4, Meta CAPI & Server-Side Events

This is for teams running a custom Laravel app, such as a SaaS, marketplace, booking system or store, who need ad platforms to see real sign-ups, bookings and payments. There's no plugin to install, so tracking has to be designed into the app. I write the event spec, work with your developers on the dataLayer and server events, and set up GTM and server-side GTM to deliver them.

Laravel · Ecommerce & lead gen
  • A written dataLayer contract your developers can build against
  • Conversions confirmed by your backend, not guessed from page views
  • Server-side events sent from queued jobs, so requests stay fast
  • Meta CAPI, GA4 Measurement Protocol and Google Ads offline conversions
Quick answer

Proper Laravel tracking means a documented event spec, dataLayer pushes rendered from Blade or your frontend after an action succeeds, and server-side events sent from controllers, listeners or queued jobs once the backend confirms the conversion. GTM handles browser tags, and server events go to Meta CAPI, GA4 and Google Ads with shared IDs for deduplication.

Tracking flow

How tracking works on Laravel

The events I set up on Laravel, and where each one is sent.

Why it breaks

Why Laravel tracking goes wrong

Conversions fire before they're real

Tracking is often tied to a button click or a front-end success message. Validation failures, declined payments and duplicate submissions still count as conversions.

Redirects lose the event

A typical Laravel flow posts a form, then redirects. If the dataLayer push isn't carried across the redirect, for example in session flash data, the event never reaches the browser.

Payments complete in webhooks

With Stripe, Paddle or similar, the real confirmation arrives as a webhook to your app, often after the customer has left. Browser-only tracking misses these, and subscription renewals never show up at all.

Client IDs aren't stored

Server events need the GA4 client ID, Meta's fbp and fbc values and the gclid from the visit. If the app doesn't save them with the user or order, server events can't be tied back to ads.

SPA front-ends miss page views

Apps using Inertia, Livewire navigation or a separate Vue or React front-end change pages without a full reload, so page views and funnels need history-based tracking.

What I set up

My Laravel tracking setup

Event spec & dataLayer

  • Written event spec with names, parameters and when each fires
  • Blade partial or component that renders dataLayer pushes
  • Session flash pattern so events survive redirects
  • Ecommerce or sign-up events in GA4's recommended format
  • Page view handling for Inertia, Livewire or SPA front-ends

Server-side events

  • Events sent from listeners or queued jobs after the backend confirms
  • GA4 Measurement Protocol with the stored client ID
  • Meta Conversions API with hashed email and phone, fbp and fbc
  • Payment webhooks (Stripe or similar) turned into purchase events
  • Server-side GTM on Stape or Google Cloud as the single endpoint

Google Ads

  • gclid, gbraid and wbraid captured and stored with the user
  • Browser conversions with enhanced conversions
  • Offline conversion uploads for trials, qualified leads or paid plans
  • Conversion values that reflect real revenue

QA & handover

  • Staging and production test plan
  • Deduplication checks between browser and server events
  • Consent Mode v2 with your consent banner
  • Logging for failed server sends
  • Handover notes for your developers
Event map

Events I track on Laravel

EventWhen it firesSent to
sign_up / CompleteRegistrationAccount created and saved by the backendGA4, Google Ads, Meta Pixel + CAPI
generate_lead / LeadForm request validated and storedGA4, Google Ads, Meta Pixel + CAPI
begin_checkout / InitiateCheckoutCheckout or plan selection page loadsGA4, Meta Pixel
purchase / PurchasePayment confirmed by your payment provider's webhookGA4, Google Ads, Meta CAPI, TikTok
start_trial / StartTrialTrial created in the appGA4, Meta Pixel + CAPI
subscription_renewedRenewal webhook processed by a queued jobGA4 (server), Google Ads offline
qualified_lead (offline)Lead marked qualified or won in your adminGoogle Ads, Meta CAPI
Process

How the setup works

  1. 01

    Map the conversions

    We list the actions that matter to the business and where in the app each one is confirmed: a controller, a model event or a webhook.

  2. 02

    Write the spec

    I write the dataLayer and server event spec, including the IDs to store, so your developers know exactly what to build.

  3. 03

    Build together

    Your team adds the Blade pushes, stored IDs and queued jobs; I build the GTM and server-side GTM containers that receive them.

  4. 04

    Test end to end

    I test on staging and production, checking each event in GA4 DebugView, Meta Events Manager and Google Ads, and that duplicates are removed.

  5. 05

    Hand over

    You get the spec, container notes and a checklist for adding new events as the app grows.

Browser events from Blade

The simplest reliable pattern is to push events after the server has done its work. The controller saves the record, puts the event and its parameters in session flash data, and redirects. The next page renders a small Blade partial that writes the dataLayer push, and GTM picks it up. Because the push only appears after a successful save, failed submissions are never counted.

Each push includes an event ID generated on the server. The same ID is used in the matching server event, which is what lets Meta and other platforms deduplicate the two.

Server-side events from controllers and queues

For conversions that matter most, such as payments, I have the app send a server event as well. A listener or queued job builds the payload with the stored GA4 client ID, Meta's fbp and fbc values, hashed customer details and the event ID, then sends it to server-side GTM. From there it goes to GA4 via Measurement Protocol, Meta CAPI and other platforms.

Queuing keeps requests fast and lets failed sends retry. It also means events that happen with no browser involved, like webhook-confirmed payments or renewals, still reach your ad platforms.

FAQ

Laravel tracking FAQ

Is there a Laravel package for GA4 or Meta CAPI?

There are community packages, but I usually recommend a small amount of your own code plus server-side GTM. That keeps the app's job simple, one endpoint, while GTM handles the details of each platform.

Do I need server-side tracking on a Laravel app?

For anything confirmed by the backend or a webhook, such as payments and renewals, yes. Browser tracking alone misses conversions that happen after the visitor leaves, and is affected by ad blockers and browser limits.

How do I send GA4 events from PHP?

Use GA4's Measurement Protocol with your measurement ID, an API secret and the visitor's client ID from the _ga cookie. Sending it through server-side GTM instead lets you reuse the same event for Meta and other platforms.

How do I avoid double counting browser and server events?

Generate one event ID on the server and use it in both the dataLayer push and the server event. Meta deduplicates on that ID, and for GA4 I only send the server copy for events the browser can't see.

Can you work alongside my developers?

Yes, that's the usual setup. I write the spec and build the GTM side; your developers make the app changes. I review pull requests if you want a second pair of eyes on the tracking code.

Guides

Read next

Want your Laravel tracking fixed?

Get a free audit of your tracking and ad account. Usually replies within 1–2 hours.