pixellint

Analytics · engineers · marketers

DebugView is not production

These tools answer 'did my device send it'. They do not answer 'did last week's 50k purchasers send it'. Do not ship based only on a green DebugView.

GA4 DebugView and the MP debug endpoint

debug_mode on the event plus DebugView in the GA4 UI shows your device. Measurement Protocol has a separate debug endpoint, /debug/mp/collect, that returns validation JSON instead of 204. They are not interchangeable with Meta's test_event_code. Hitting the debug URL with a production api_secret still validates the contract; it may not count the event. Do not point production traffic at /debug/mp/collect.

Leave debug_mode on in production and you keep a debug stream in a UI nobody watches, or you pollute DebugView with real users. Strip it with a build flag. timestamp_micros can still be 13 digits in a hit that looks fine in DebugView if you only glance at the event name.

POST /debug/mp/collect?measurement_id=G-XXXXXXX&api_secret=SECRET HTTP/1.1
Host: www.google-analytics.com

{"client_id":"debug.1","timestamp_micros":1770000000000000,"events":[{"name":"purchase","params":{"debug_mode":1,"currency":"USD","value":1,"transaction_id":"QA-1","items":[]}}]}

Meta Test Events

test_event_code routes the payload into the Test Events UI. It does not point at a sandbox graph with fake users. Production tokens plus a test code is still your real pixel id. Pixellint warns vendor.meta-conversions-api.testing.test_event_code_present because leftover codes divert production. Strip them in prod with a flag, not a comment.

Pixel Helper is the browser pipe. Test Events is the server pipe (and can show the pixel too). Both pipes, same event_id (fbq eventID versus CAPI event_id). If only one appears, you proved half the design. Empty Test Events means you are not live, even if GTM says the tag fired.

GTM preview is not the published container

Preview attaches a debug panel to a draft or a selected version. Users without the debug cookie get the published container. Shipping based on preview alone is how unpublished tags look fine. Preview, submit, publish, then Network on a clean browser with no preview cookie. That third step is the one people skip.

See GTM preview versus production. Agencies leave old versions. Rollbacks reintroduce Purchse. Consent Overview in preview is not a guarantee Custom HTML respected the CMP on a fresh profile.

What a green personal hit does not prove

It does not prove currency is present on 99% of purchases. It does not prove Safari sent _fbp. It does not prove the collect hit used v=2 and a G- tid. It does not prove the CAPI worker uses seconds rather than Date.now(). It proves your laptop can talk to the collector.

Pair DebugView with fixtures in CI: pixellint validate json on MP and CAPI bodies, pixellint validate url on collect and facebook.com/tr. Sample the export for the rate. Staging ids so QA purchases never train production.

pixellint validate json @mp.json --rulepack vendor/google-analytics
pixellint validate json @capi.json --rulepack vendor/meta-conversions-api
pixellint validate url @pixel.txt --rulepack vendor/meta

Turn it off

A launch checklist that never mentions removing debug_mode, test_event_code, and the GTM preview cookie is how last month's QA still shows up in Test Events, or how DebugView is unusable because every user is debug. Treat leftover test flags as production incidents.

Pixellint is not affiliated with Google or Meta. Debug UIs are QA surfaces. Production is the published container, the production MP endpoint, and CAPI without a test code.

Check the artifact

Paste the pixel URL or JSON body into the playground. Same engine as pixellint validate. Nothing leaves the tab.