Fix tracking that is not working
Diagnose missing events, consent setup, refused batches, identity gaps, and conversion failures.
Find the symptom below and work through its checks in order. Have the affected page, Tracking’s Live feed, and any backend response available. Use the final observable check to confirm the fix; a successful network response alone may not mean events were stored.
Symptom | Go to |
|---|---|
Nothing arrives at all | |
A hostname you did not expect | |
A domain stuck on Waiting for events | |
Tracking domain will not verify | |
Your backend gets an error | |
Events not stored this month | |
Cookies appear before a banner answer | |
All visits stay cookieless | |
Money accepted but not visible | |
Someone stays Anonymous | |
Far more events than people | |
Google shows no conversions | |
A workflow never starts |
No events at all
Use these checks when Live has no events, including when it is still waiting for the first one.
- Inspect the deployed page source. Confirm that the tracking snippet is in the
<head>of the page you loaded, not just the home page. - Publish the change. A template or builder edit does not affect visitors until deployed.
- Load Tracking unconditionally. Rendering it only after consent hides declining and undecided visitors. On pages using the Lepsto banner, add
data-consent="banner"and put the banner first; see Install the script. - Rule out a content blocker. Test in another browser or without browser add-ons.
- Use the loader for custom calls. With the minimal variant,
lt(…)called before script load throws and loses the event. - Check for storage refusals. If
Events not stored this monthappears, follow the storage checks.
Verify it works: load a page after the fix and find its page_view in Live.
Events from an unexpected hostname
The Also sending events list can reveal hostnames missing from your checklist.
- Compare the registered hostname with the one serving visitors. Acme’s
acme.comandwww.acme.comare separate entries; replace these examples with your own hostnames. - Use
Add to checklistfor the active hostname and remove an unused entry. - Verify it works: the expected hostname appears as
Script seenafter its event arrives.
The list reports installation rather than filtering collection. Removing a hostname does not stop its events. See Domain lists.
The install checklist never turns green
Follow this path when a listed domain remains Waiting for events.
- Visit a deployed page on that exact hostname to generate traffic.
- Compare its spelling with
Also sending events, includingwwwand subdomains. - Confirm the snippet is present on that page.
- Wait for the checklist’s roughly ten-second refresh.
- Check the latest event date: after 30 days without traffic, a hostname returns to
Waiting for events. - Verify it works: the row changes to
Script seenand shows the new event time.
Declining consent alone does not prevent verification. Cookieless events still carry the page address, so stored events can confirm its hostname. A tag hidden behind a consent check sends nothing; a storage refusal can also prevent confirmation.
The tracking host stays unverified
Use these checks for Waiting for DNS to publish or Verification failed on Tracking domain.
- At your DNS provider, publish the exact records shown for the claimed host.
- Select
Check nowafter publication. - Inspect what the host serves: verification requires the tracking JavaScript, not a redirect, parked page, or error response.
- Read the last failure reason for its status, content type, redirect, or lack of response.
- Use
Retrywhen the host is ready. Automatic checks stop after 72 hours; DNS propagation has its own timing and can outlast those checks. - Verify it works: the binding becomes
Activeand the generated snippet uses the claimed host.
Once active, replace the snippet on your site with the current version from Install; its host is part of the pasted HTML.
The events route rejects the request
Read the HTTP status and body when the Events API does not return batch counts.
Key failures are checked at the edge and return { "error": { "code": …, "step": "public_key_check" } }. A newly created or changed key can take about 30 seconds to propagate. See Backend access keys.
What you get | What it means | Fix |
|---|---|---|
401 public_key_required | No key reached the edge | Send the key as Authorization: Bearer <your key>. X-Public-Key and the legacy X-Api-Key carry it too, but a request with none of them is refused. |
401 public_key_invalid | The key is not one of this product’s keys | Check you are not pointing a staging key at production. A revoked key returns this error too. Key changes can take about 30 seconds to reach the edge. |
403 public_key_scope | The key is real, but its scope does not cover the Events API | Ask a product Owner or Admin to widen the key’s scope in Product → Settings → Public Access, or use a key that covers the tracking toolkit. |
503 public_config_unavailable | The edge has not loaded its key snapshot yet and fails closed | Retry. Nothing about your key or your request is wrong. |
400 request body must be { "events": [ … ] } | The envelope is wrong | Wrap your events in an events array. |
400 events batch exceeds the 500-event limit | Too many events | Split the batch. |
413 | The body is over 64 KiB | Send fewer events per request. |
402 entitlement_exhausted | The whole batch was refused without storage | Read reason: resolve trial_cap_reached, billing_paused, or budget_paused on the organization’s Billing page. Do not repeat the request while the condition remains. |
A 200 with a nonempty rejected list means valid events were stored and individual entries failed validation. Read each reason; common causes are missing payment/refund amounts, missing currency, or a timestamp over 24 hours ahead or about 90 days behind. Correct those entries and inspect the next batch’s accepted, duplicates, and rejected counts. See Revenue fields and Public HTTP errors.
Events not stored this month
If events keep leaving the browser but reports stop growing, check the notice on Dashboard, Live, or Reports.
- Read
Events not stored this monthfor the number lost and when loss began. It counts collector events that were never stored during the current UTC month, not stored-event volume. Refused backend batches return402and are excluded from this count. The notice remains until the UTC month ends and cannot be dismissed. - Open the organization’s
Billingpage. For a trial allowance, upgrade or wait for the next calendar month. For paused billing or a reached budget, resolve the condition and resume usage. - Verify recovery: generate a fresh event and confirm it appears in
Live. Previously dropped browser events remain lost. Backend events you retained can be resent after resolution, using the same ids and respecting the writable timestamp window.
A collector 204 does not prove storage. See Public HTTP routes for the different collector and Events API responses.
Revenue is not showing
First confirm the Events API accepted the payment, then check the view where you expect it.
- Open the person’s journey for the new payment.
Lifetime valueupdates on a schedule and can lag by up to an hour. - Check the event’s
emailor capturedanonymous_id. Without either, revenue has no person, so there is no customer or lifetime-value entry and the amount is unattributed. - Check minor units:
49with EUR means EUR 0.49, not EUR 49.00. - Check each currency separately; amounts in different currencies are not added.
- For
Revenue by source, confirm asubscription_startedevent withprops.subscription_ref. Payments alone do not create its paid conversion. - Check the person’s first conversion date. A recent renewal from someone who first converted before the selected range is excluded.
- Verify it works: find the accepted payment in the journey, then confirm the appropriate lifetime-value currency and report cohort.
A person is not identified
Use these checks when you expected a known identity but People still shows Anonymous.
- Confirm your code sends
lt('identify', …)or a backend event withemail. A submitted form or email in ordinarytrackproperties does not identify anyone. - Put the call where you learn the visitor’s own address: sign-up, sign-in, social login, or a signed-in page load.
- Exclude invitation, gift, and referral forms containing someone else’s address. Identifying from them misattributes visits without an error, and removing the call does not repair past attribution.
- Check consent: a cookieless browser drops
identifyentirely. The backend identity path is separate. - Prefer phone numbers with
+and 8–15 digits. Plain 10- or 11-digit North American numbers also work; other formats can be ignored. - Repeat
identifyon signed-in page loads to recognize the visitor after cookie loss. - Verify it works: find the person by email and confirm their status and journey.
See Identify a visitor and What tracking does with a consent answer.
Far more events than people, or a funnel that empties out
A gap between event totals and people or funnel steps can reflect consent coverage. It does not by itself prove an event was lost.
- Check browser consent. Stored cookieless events appear in totals,
Events, andLivewithout creating or joining a person. - Separate browser history from backend data. Cookieless events cannot form person-based funnels or source attribution, but backend events can still identify a customer and record revenue.
- Read Google Ads paid tracking health for its cookieless paid-click share. That figure covers paid traffic, not all visitors.
- Confirm that the banner does not hide the tracking tag. Conditional loading can remove declining visitors from event totals too.
- For full-mode visits, confirm identification calls or backend emails are present.
- Verify the explanation: compare stored event counts, consent coverage, and a known person’s journey rather than expecting a one-event-to-one-person ratio.
See What tracking does with a consent answer and Read the attribution reports.
Google Ads conversions are not arriving
If conversion feedback is enabled but Google shows no conversions, trace the last upload pass.
- Confirm the account is connected; otherwise
Conversionsshows the connection prompt. - Check both the master switch and the relevant rule are enabled.
- Select
Run nowinstead of waiting for the daily pass. - Read
Upload statusfor considered, click-matched, and uploaded counts and exclusion reasons. - For
No click id found, check paid tracking health and Google auto-tagging. Uploads needgclid; cookieless browser clicks do not carry it. - For
no value yet, check whether revenue has arrived. These conversions can be picked up by a later pass. - Verify the result: inspect the conversion’s
Upload logoutcome and any failure reason. An uploaded conversion can take hours to appear in Google.
See Close the loop on Google Ads.
Cookies appear before the banner answer
On a page using the Lepsto consent banner, check the declaration before testing an undecided visit.
- Add
data-consent="banner"to the tracking script tag, or request the snippet withconsentBanner: true. - Put the banner first in
<head>withoutasyncordefer. - Verify it works: in a fresh visit without a recorded consent decision, confirm Tracking creates neither
_lt_aidnor_lt_sidbefore the answer. Adding the declaration does not delete cookies created earlier. A previously accepted decision still enables full mode.
See Install the tracking script.
Every visitor stays cookieless
- Remove
data-consent="banner"from pages that do not run the Lepsto banner. They cannot supply the decision the declaration expects. - On declared pages, confirm the banner loads and acceptance stores
lepsto_consent. Older saved decisions are read and migrated automatically. - Verify it works: after acceptance, the page moves to full mode without reloading. A banner that never loads leaves an undecided page cookieless.
See Tracking and consent.
A workflow does not run when the event happens
If an event appears in Live without starting its workflow, check the trigger configuration and timing.
- In
Events, enableWorkflow triggeron the exact event name. Names default to off. - Wait about a minute for the change before sending another test event.
- Compare the trigger filter character for character:
Paymentandpaymentare different names. - Confirm the test event is in
Live; backend events can trigger the same workflow. If it is absent, start with delivery checks. - Check the workflow is published and enabled.
- Verify it works: send a fresh matching event and inspect the workflow run and its output.
After disabling the checkbox, allow the same minute for publication to stop.
See Trigger a workflow from a tracked event.
Nothing here matches
Inspect the raw event surfaces before interpreting a report:
Live— the events as they arrive, with the page, the source and the visitor behind each one.Events— every event name your sites have ever sent, with counts. A typo shows up here as a near-duplicate row with a small count.
When Live contains the expected event but a report excludes it, check the report’s attribution rules, identity, and date selection.
Next steps
- Read the attribution reports: what each number in a report actually counts.
- Register the domains you track: the three domain lists and how each is verified.
- What tracking does with a consent answer: how cookieless browser events differ from backend identity.
- The public HTTP routes and SDK: the exact error bodies the Events API returns.
- Look up a setting: every default and every limit in one place.