pixellint

Validate a pixel or conversion API

Paste a URL from the Network tab, or the JSON your server posts.

Or try an example.
More examples

Privacy ·

The conversions API said 200. The purchase never landed.

A conversions API can return 200 and still drop the purchase. The box above checks the fields the vendor documented.

Systems the checks have run on

The same check runs in the CLI, in CI, and for agents.

Put the fixtures in CI, and keep production HARs out of tickets.

cargo install pixellint
npm install pixellint
pixellint validate url 'https://www.facebook.com/tr?ev=Purchase'
pixellint validate json @payload.json --rulepack vendor/meta-conversions-api

GitHub · crates.io · npm · MCP: cargo install pixellint-mcp

Conversions API questions

How do I validate a conversion API payload?

Paste the CAPI JSON into the box above, with Format set to JSON, or run pixellint validate json. HTTP 200 from the vendor is not that check.

What is a website pixel checker?

A website pixel checker lints the collector URL from Chrome Network. Paste facebook.com/tr or another pixel into the box above. CAPI JSON is a different paste, with Format set to JSON.

Why is my Facebook pixel not firing?

Filter Chrome Network for facebook.com/tr. If that request is missing, the pixel is not firing. If /tr is present, the pixel fired and the event name or parameters may still be wrong.

Why does the Conversions API return 200 if Test Events is empty?

Vendors accept malformed events and still return 200. A 13-digit event_time, a raw email in em, or website without event_source_url can all 200.

More questions

Why is CAPI not working?

CAPI not working is usually HTTP 200 with empty Test Events, not a dead token. Lint the JSON before you rotate the token.

Is Facebook Pixel Helper enough to debug a tracking pixel?

Pixel Helper cannot see conversion API POSTs. Chrome Network is the fired URL. Pixellint lints that URL against the documented contract.

The latest note from the measurement stack.

Contract pages stay in docs. All posts · RSS.

Start with the guide for the job.

All docs.

Ten reasons a 200 is not a pass.
  • Broken pixels return 200. A malformed conversion event is accepted and nothing reports it wrong. You find out at month-end reconciliation, if at all.
  • Every endpoint wants a different clock. Meta takes seconds, LinkedIn milliseconds, GA4 microseconds, Amplitude milliseconds, PostHog and Braze ISO 8601. Send the wrong unit and the event is accepted, dated 1970.
  • A purchase with no value reports no revenue. Meta and GA4 both document value and currency as required for purchase events. Neither rejects the event when they are missing.
  • Hashing goes wrong in both directions. A raw email in user_data is a privacy incident. A hashed IP address makes the event unmatchable. On the wire they look the same.
  • gdpr_consent=1 passes a format check. It is valid base64. Only decoding the version field shows it carries no consent at all, which is legal exposure behind a green response.
  • Server-side has no console. Conversion APIs are raw JSON posted from your backend. No network tab, no browser warning, no consent tool to object.
  • Findings cite the vendor's own documentation. With the URL. That turns "I think the tag is wrong" into a ticket the other team can act on.
  • It runs before launch. A terminal, CI, an MCP server for agents, an npm package, or this page. Catching a defect at QA costs minutes; catching it after spend costs the campaign.
  • Vendor rules only fire on vendor endpoints. No noise on an endpoint it does not understand, and no invented rules either. Unknown hosts get attribution, not findings.
  • One tool, not seven vendor debuggers. Browser pixels, conversion APIs, and the analytics tier, with the same output and the same exit codes across all of them.

Every contract has its own page.

Rulepacks

One page per pack.

Vendor directory

Each host is attributed to one vendor.