Skip to main content
GUIDE · DEBUGGING11 min read

Debugging server-side tracking: where conversions actually go missing

A practical guide for tracing a missing conversion through TrackLayer from intake to enrichment to platform attribution, without jumping straight into a destination dashboard and guessing where the failure happened.

Framework

The debug pyramid

Most teams debug server-side tracking upside down. They open Meta Events Manager, see nothing useful, and start changing payloads before they know whether the event even reached TrackLayer. That usually creates more noise than signal. A better approach is a five-layer pyramid that mirrors the real delivery path from source event to attributed conversion.

Work top-down. Each layer depends on the one before it. If Layer A fails, Layers B through E are irrelevant. If Layer C is clean but Layer D rejects the payload, the platform dashboard is not the primary debugging tool. This order reduces guesswork, shortens incident time, and makes support tickets much easier to resolve.

Layer A
Check `/events` live stream

Is the event arriving at TrackLayer?

If the event never appears in the live stream, stop there. Nothing downstream can recover it. This is where you validate SDK initialization, API key validity, browser-to-server transport, queue backpressure, and whether the request is being rate-limited before TrackLayer stores the event.

Layer B
Check dedup + hashing logs

Is TrackLayer enriching properly?

An arriving event can still fail quietly if normalization mutates identifiers, drops user_data fields, or generates the wrong event_id. Review enrichment output for normalized email, phone, currency, order identifiers, consent state, and hashed fields to confirm the platform-ready payload is coherent.

Layer C
Check `/deliveries`

Is delivery attempted to the platform?

Delivery status answers whether TrackLayer actually tried to send the event to Meta, TikTok, Google Ads, Klaviyo, or another destination. If no delivery record exists, the routing rule, consent rule, destination toggle, or event mapping is usually the real problem.

Layer D
Check `/api-logs` response codes

Is the platform accepting it?

A delivery attempt is not the same thing as acceptance. The raw destination response tells you whether the payload was accepted, partially accepted, rejected, throttled, or ignored due to schema errors. This is where you catch 400 payload problems, 401 auth issues, 403 permissions, and 429 retry storms.

Layer E
Check platform Events Manager

Is the platform attributing it correctly?

Even an accepted event can show weak or delayed attribution if dedup is wrong, click IDs are missing, cookies are absent, consent suppresses matching identifiers, or the platform decides the event is out of attribution window. This last layer is about reporting quality, not transport success.

Inspection

5 tools for each layer

Each layer has one best inspection surface. The goal is not to use every screen. The goal is to use the smallest number of screens that let you compare intent, actual payload, delivery behavior, and platform feedback with minimal interpretation.

Layer A

Chrome DevTools network tab + TrackLayer live event stream

Open DevTools, reproduce the action, and inspect the request that should create the event. Confirm status code, payload size, request timing, and whether retries or CORS failures appear. Then compare the same moment in TrackLayer live stream. If DevTools shows a request but `/events` stays silent, focus on auth, edge rejection, or queueing.

Layer B

`/events` detail drawer → raw payload JSON

Use the detail drawer to compare the inbound payload against the enriched payload. This is the fastest place to catch malformed `event_name`, missing `event_id`, wrongly cased currency, unnormalized email, and unexpected null values. When match quality is low, this drawer usually shows why in one screen.

Layer C

`/deliveries` status chip

The `delivered`, `failed`, and `pending` chips tell you whether routing is alive and whether retries are still in flight. A pile of `pending` deliveries usually points to worker backlog or destination throttling. A clean event with no delivery row usually means the destination rule never matched.

Layer D

`/api-logs` response body inspection

Read the full response body instead of stopping at the HTTP code. Many platforms return structured warnings such as missing `fbp`, invalid `event_time`, unsupported parameter names, or partially accepted user_data. Those details tell you whether to fix transport, schema, or identity.

Layer E

Meta Events Manager → Test Events → Diagnostics

Use the destination dashboard only after the first four layers are clean. In Meta, Test Events confirms real-time arrival, while Diagnostics explains match quality issues, dedup collisions, or parameter mistakes. Apply the same pattern on other platforms: verify arrival, then verify attribution health.

Diagnosis

Common symptom → likely cause

This table is a triage tool, not a substitute for logs. Use it to decide which layer to inspect next. The fastest investigations are the ones where the symptom immediately narrows the search surface.

SymptomCheckLikely cause
No events in live streamAPI key, rate limit, SDK initThe request is never authenticated or never leaves the page or backend worker in the first place.
Events arrive but match quality stuck at 4Email hash normalizationWhitespace, casing, or pre-hashed values often prevent the platform from matching what should be strong identifiers.
Purchase events but Meta doesn’t countevent_id dedup + fbp cookie forwardingAccepted events can still fail attribution when Meta sees a dedup conflict or lacks browser identifiers for matching.
Event visible in `/events` but no `/deliveries` rowDestination routing ruleThe event is stored but not eligible for the destination because mapping, consent, or toggle conditions skip it.
Delivery stuck on pending for minutesWorker backlog or 429 retriesThe delivery queue is alive but delayed, usually because the destination is throttling or workers are saturated.
High failed-delivery count after a deploySecret rotation and environment varsA rotated token, wrong project environment, or missing secret often appears immediately after deployment changes.
Google Ads enhanced conversions accepted but weakUser-provided data formattingPhone, email, and address inputs must be normalized consistently before hashing or Google will accept low-quality identifiers.
Events duplicate across Pixel + CAPIShared event_id across browser and serverIf the browser and server generate different IDs for one action, the platform counts two conversions instead of one deduped event.
Only some orders reach the destinationConsent branch and order-source filtersMixed consent states, channel-specific routing, or source-based exclusions can make the issue look random when it is rule-driven.
Test event works but production attribution lagsAttribution window and click IDsTest tools confirm transport, but production credit still depends on fresh click identifiers and valid attribution timing.
Refund or cancellation events never appearCanonical event mappingNon-standard internal event names often never map to the destination event type expected by the integration.
Klaviyo receives profile updates but not purchase metricsMetric payload shape and metric nameProfiles can be valid while event creation still fails because the metric object or event time is malformed.
Dedup

The dedup diagnostic

The classic complaint is simple: “my Pixel + CAPI are double-counting.” The underlying causes are usually simple too, but only if you debug one conversion at a time. A clean dedup investigation should prove whether browser and server are talking about the same action, whether they share one `event_id`, and whether the destination had enough identifiers to merge them.

01

Start with one known order

Pick a single checkout from a test user and collect the browser event timestamp, Pixel request, server event timestamp, and TrackLayer event_id. Debugging dedup with a broad date range is slow because noise hides the exact collision you need.

02

Compare event_id on both paths

Open the browser payload and the TrackLayer delivery payload side by side. The `event_name` and `event_id` must describe the same user action. If the browser sends `purchase_click_123` and the server sends `order_987_paid`, Meta treats them as different conversions.

03

Check arrival timing, not just content

Large timing gaps can produce misleading diagnostics. If the browser fires immediately but the server arrives much later after retries, the platform may still dedup, but reporting can look unstable for a while. Review both timestamps before concluding that content is wrong.

04

Inspect platform diagnostics for dedup warnings

Meta Diagnostics and Test Events usually show whether the browser event or server event was favored and whether identifiers were insufficient. That tells you whether to fix ID parity, browser cookie forwarding, or simply delivery latency.

05

Fix ID generation at the source

Do not patch dedup downstream with ad hoc rewrites. Generate one durable `event_id` when the business action is created, store it on the order or checkout entity, and reuse it everywhere: pixel, webhook, replay, and TrackLayer delivery.

Consent

The consent diagnostic

Consent bugs are easy to misread because the system may be doing exactly what policy says while the operator expects marketing attribution behavior. The right way to debug consent is to trace a single user journey from banner choice to event payload to routing decision to platform outcome. That separates genuine bugs from intended suppression.

Step 1

Record the banner decision

Start at the consent banner and capture exactly what the user accepted or rejected. If analytics consent is denied but marketing consent is granted, your routing behavior should show that distinction explicitly instead of collapsing everything into a generic blocked state.

Step 2

Confirm consent state on the event

Open the event in `/events` and inspect the consent fields captured at collection time. If consent is missing here, the problem is not destination delivery. It is state propagation between the frontend banner, backend session, and TrackLayer ingestion.

Step 3

Inspect the routing decision

In `/deliveries`, verify whether the destination was intentionally skipped, delayed, or allowed. A skipped delivery with a clear consent reason is correct behavior. A missing reason usually means the routing rules are opaque or incomplete.

Step 4

Validate what was stripped before send

Some merchants permit event forwarding without marketing identifiers when consent is limited. In that case the payload may be sent but with hashed identifiers, cookies, or click IDs removed. The event will arrive but match quality will drop, which is expected and should be visible in logs.

Step 5

Cross-check the platform result

Finally, open the platform diagnostics and confirm that the event behavior matches the consent policy you intended. If the policy says send a purchase with limited identity, you should see the event with weaker attribution, not a completely missing conversion.

Platforms

Platform-specific diagnostic URLs

Support

When to open a TrackLayer support ticket

Open a ticket after you have isolated the layer, not before. A vague “Meta is missing purchases” report forces everyone to re-run the same checks. A precise ticket gives TrackLayer enough context to inspect worker history, destination formatting, or internal retries immediately.

You can reproduce the issue with one specific event_id and TrackLayer shows behavior that conflicts with its own logs.

The platform response is ambiguous or contradictory, for example accepted in `/api-logs` but never visible in test tools after repeated controlled sends.

The problem spans multiple merchants or multiple destinations at the same time, which usually points to infrastructure or shared routing changes.

You have already isolated the layer and need TrackLayer to inspect internal worker state, retry history, or destination-specific formatter output.

Include the following fields every time so the investigation can start from one concrete event instead of a time range.

  • event_id
  • timestamp
  • merchant_id
  • affected platform
  • expected vs actual
FAQ

Common questions

What is the first screen I should open when a conversion is missing?

Open `/events` first. If the event is not there, every later dashboard is noise. The live stream tells you whether TrackLayer ever received the action you are trying to debug.

Why do accepted events still fail to show up in reporting?

Acceptance only means the API received the payload. Reporting still depends on attribution rules, click identifiers, cookies, consent state, dedup behavior, and the platform’s own processing delay.

Should I debug in the platform before TrackLayer?

No. That reverses the dependency chain and wastes time. Start at collection, then enrichment, then delivery, then API response, and only then attribution dashboards.

How long should I wait before calling an event missing?

For real-time testing, give the destination a few minutes unless the API explicitly rejected it. For attribution reports, some platforms lag longer, so use Test Events or diagnostics rather than waiting on aggregated reporting.

What is the most common root cause in double-counting investigations?

Different `event_id` values for the browser and server version of the same conversion. The second most common cause is forwarding the server event without the browser identifiers needed for confident dedup.

Next reads

Related implementation guides

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.