Skip to content

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.

  1. Inspect the deployed page source. Confirm that the tracking snippet is in the <head> of the page you loaded, not just the home page.
  2. Publish the change. A template or builder edit does not affect visitors until deployed.
  3. 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.
  4. Rule out a content blocker. Test in another browser or without browser add-ons.
  5. Use the loader for custom calls. With the minimal variant, lt(…) called before script load throws and loses the event.
  6. Check for storage refusals. If Events not stored this month appears, 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.

  1. Compare the registered hostname with the one serving visitors. Acme’s acme.com and www.acme.com are separate entries; replace these examples with your own hostnames.
  2. Use Add to checklist for the active hostname and remove an unused entry.
  3. Verify it works: the expected hostname appears as Script seen after 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.

  1. Visit a deployed page on that exact hostname to generate traffic.
  2. Compare its spelling with Also sending events, including www and subdomains.
  3. Confirm the snippet is present on that page.
  4. Wait for the checklist’s roughly ten-second refresh.
  5. Check the latest event date: after 30 days without traffic, a hostname returns to Waiting for events.
  6. Verify it works: the row changes to Script seen and 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.

  1. At your DNS provider, publish the exact records shown for the claimed host.
  2. Select Check now after publication.
  3. Inspect what the host serves: verification requires the tracking JavaScript, not a redirect, parked page, or error response.
  4. Read the last failure reason for its status, content type, redirect, or lack of response.
  5. Use Retry when the host is ready. Automatic checks stop after 72 hours; DNS propagation has its own timing and can outlast those checks.
  6. Verify it works: the binding becomes Active and 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.

  1. Read Events not stored this month for 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 return 402 and are excluded from this count. The notice remains until the UTC month ends and cannot be dismissed.
  2. Open the organization’s Billing page. 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.
  3. 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.

  1. Open the person’s journey for the new payment. Lifetime value updates on a schedule and can lag by up to an hour.
  2. Check the event’s email or captured anonymous_id. Without either, revenue has no person, so there is no customer or lifetime-value entry and the amount is unattributed.
  3. Check minor units: 49 with EUR means EUR 0.49, not EUR 49.00.
  4. Check each currency separately; amounts in different currencies are not added.
  5. For Revenue by source, confirm a subscription_started event with props.subscription_ref. Payments alone do not create its paid conversion.
  6. Check the person’s first conversion date. A recent renewal from someone who first converted before the selected range is excluded.
  7. 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.

  1. Confirm your code sends lt('identify', …) or a backend event with email. A submitted form or email in ordinary track properties does not identify anyone.
  2. Put the call where you learn the visitor’s own address: sign-up, sign-in, social login, or a signed-in page load.
  3. 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.
  4. Check consent: a cookieless browser drops identify entirely. The backend identity path is separate.
  5. Prefer phone numbers with + and 8–15 digits. Plain 10- or 11-digit North American numbers also work; other formats can be ignored.
  6. Repeat identify on signed-in page loads to recognize the visitor after cookie loss.
  7. 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.

  1. Check browser consent. Stored cookieless events appear in totals, Events, and Live without creating or joining a person.
  2. 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.
  3. Read Google Ads paid tracking health for its cookieless paid-click share. That figure covers paid traffic, not all visitors.
  4. Confirm that the banner does not hide the tracking tag. Conditional loading can remove declining visitors from event totals too.
  5. For full-mode visits, confirm identification calls or backend emails are present.
  6. 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.

If conversion feedback is enabled but Google shows no conversions, trace the last upload pass.

  1. Confirm the account is connected; otherwise Conversions shows the connection prompt.
  2. Check both the master switch and the relevant rule are enabled.
  3. Select Run now instead of waiting for the daily pass.
  4. Read Upload status for considered, click-matched, and uploaded counts and exclusion reasons.
  5. For No click id found, check paid tracking health and Google auto-tagging. Uploads need gclid; cookieless browser clicks do not carry it.
  6. For no value yet, check whether revenue has arrived. These conversions can be picked up by a later pass.
  7. Verify the result: inspect the conversion’s Upload log outcome 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.

  1. Add data-consent="banner" to the tracking script tag, or request the snippet with consentBanner: true.
  2. Put the banner first in <head> without async or defer.
  3. Verify it works: in a fresh visit without a recorded consent decision, confirm Tracking creates neither _lt_aid nor _lt_sid before 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

  1. Remove data-consent="banner" from pages that do not run the Lepsto banner. They cannot supply the decision the declaration expects.
  2. On declared pages, confirm the banner loads and acceptance stores lepsto_consent. Older saved decisions are read and migrated automatically.
  3. 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.

  1. In Events, enable Workflow trigger on the exact event name. Names default to off.
  2. Wait about a minute for the change before sending another test event.
  3. Compare the trigger filter character for character: Payment and payment are different names.
  4. Confirm the test event is in Live; backend events can trigger the same workflow. If it is absent, start with delivery checks.
  5. Check the workflow is published and enabled.
  6. 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

Was this page helpful?
Esc

Start typing to search the docs.

↑↓navigate↵select