Empty Test Events means you are not live
GTM can say the tag fired while Events Manager stays empty. You need both pipes, a shared event_id, value and currency on money events, and a refund plan. These pages are the ones to walk before you raise bids.
Validate a pixel or CAPI All docs
Pixels and tags
How does a tracking pixel differ from a cookie?
A tracking pixel sends an event to a collector. A cookie stores a value that may be sent with a later request. See what survives when cookies are blocked and how to inspect both in DevTools.
How do Meta Pixel and Google Ads conversion tags compare?
Meta Pixel and Google Ads tags can report the same purchase to different ad systems. Compare their event names, conversion IDs, click identifiers, deduplication, and QA steps.
What is a tracking pixel
A tracking pixel is an HTTP request that records an ad impression, click, page view, or conversion. The transport may be a 1x1 image GET, navigator.sendBeacon, or fetch. Email open pixels and VAST Impression beacons are the same job on different surfaces.
Image pixel vs JavaScript tag
A 1x1 image pixel can only send what fits in a GET URL, about two thousand characters in practice. Floodlight and LinkedIn Insight still ship images. fbq, gtag, and ttq can POST a body, read cookies, and hash emails. CSP and noscript treat the two transports differently.
Noscript pixel fallback
A noscript image pixel is the fallback when JavaScript does not run. Meta uses noscript=1 on facebook.com/tr. It is a different request, not a second copy of the JS event. Ad blockers that list the host will block the image too. Dedup with event_id if both can fire.
Impression pixels vs click trackers
An impression pixel fires when the creative loads and should return 200 with a 1x1 or 204. A click tracker fires on click as a 302 chain. Never 302 an impression to a landing page. View-through is a report setting, not a third pixel.
Conversion pixels vs S2S postbacks
A conversion pixel fires in the browser on the thank-you page. An MMP postback is a server-to-server GET or POST with macros expanded at conversion time. CAPI is a JSON POST to the vendor. They fail in different ways. Unexpanded macros on a fired postback are a trafficking bug.
Cache busting on impression pixels
Impression pixels need a unique query value so CDNs and browsers do not collapse thousands of impressions into one cached response. Floodlight uses ord, and unique counting also needs num. Ad servers expand [CACHEBUSTER]. Do not put PII in ord. Click URLs do not need this trick.
Redirect pixel chains
Click trackers are redirect chains. Each hop can append or drop gclid, fbclid, or an MMP id. A 200 in the middle of the chain is a broken click. http to https and apex to www redirects that drop the query string are the usual paid-search outage. Debug with curl -sIL.
UTM parameters vs click ids
utm_source, utm_medium, utm_campaign, utm_content, and utm_term are for your analytics property. Google Ads, Meta, and TikTok attribute paid clicks with gclid, fbclid, and ttclid. UTM is not a click id. Casing splits sessions. Do not put gclid in utm_content and expect Ads to see it.
Landing page vs thank-you page pixels
PageView belongs on the landing page, where click ids are stored. Purchase belongs on the thank-you page, once. Hosted checkout (Shopify, Stripe Checkout) often means the thank-you page is another host, so cookies and click ids must travel or the conversion fires as a new user. Firing Purchase on every landing inflates ROAS until the platform discounts you.
Bots, prefetch, and invalid traffic on pixels
Prefetch, Slack unfurls, Gmail image proxies, and link scanners fire pixels without a user. Platforms filter invalid traffic in the UI. Your BigQuery export of raw hits will not match. Gate conversion tags on a real order id, not on DOM Ready of a public URL.
Ad blockers and tracking pixels
Ad blockers drop known pixel hosts from EasyList and similar lists. GTM preview can say the tag fired while facebook.com/tr never leaves the machine. Noscript does not bypass a host block. Recovery is CAPI or sGTM on a first-party collector you operate, not a second request to the same listed host.
Ad server macros in pixels
Macros use [NAME], ${NAME}, {{NAME}}, %%NAME%%, !!NAME!!, and [%NAME%]. They must expand before a pixel fires. They never belong in scheme, host, or userinfo. A pixel URL uses one syntax. A VAST tracker may carry IAB [MACRO] beside ${MACRO}. gdpr_consent=1 is valid base64 and not a TC String. Pixellint core encodes these as macro and privacy rules.
Template vs fired pixel URLs
A template URL is what the ad server stores. A fired URL is what the browser requested. Pixellint artifact state is unknown, template, or fired. Template may contain macros. Fired may not. Unknown stays conservative. CI needs two fixtures, two states, one job.
Duplicate pageviews
Two PageView hits per load come from initializing fbq and GTM's Meta tag, from React 18 Strict Mode, or from History Change plus Container Load. The Network tab shows two /tr?ev=PageView or two /g/collect en=page_view hits. Deduplicate or remove a tag before you chase a platform bug.
VAST tracking events are pixels
VAST Impression, Tracking start/quartile/skip/progress, and ClickThrough are three pixel contracts on one tag. A fired start that still contains CACHEBUSTER is the same miss as a display impression that never unique-counted.
Conversion APIs
How do GA4 key events and Google Ads conversions compare?
A GA4 key event marks an important site action. A Google Ads conversion action can be created from that Analytics event or measured with an Ads tag. Learn why counts diverge and what to check before bidding.
How does conversion tracking differ from attribution?
Conversion tracking records an action. Attribution assigns credit to earlier marketing touchpoints. Diagnose a missing event, missing click ID, and differing dashboard totals in the right order.
What is a conversion API
A conversion API is a server POST that sends conversion API events. Meta names it the Conversions API (CAPI). Facebook CAPI and Meta CAPI are the same Graph events edge. TikTok names it Events API. Google names it Measurement Protocol. Same job, incompatible JSON.
Pixel plus conversion API events
CAPI implementation is browser pixel plus conversion API events, deduplicated on event_id. Drop either side without a plan and you undercount or double-count. Meta CAPI and Facebook CAPI document this hybrid.
Event match quality
Match quality is how confidently the platform attaches your event to a user. Click ids score high. Hashed email and phone help. IP plus user-agent are weak but real. Empty user data is a dark event.
Test events vs production CAPI
Meta's test_event_code and vendor debug flags keep QA out of production reporting. Forgetting to strip them, or never using them, are both ways to lie to yourself.
Offline conversions
Offline conversions upload events that never happened in the browser: phone sales, in-store POS, Salesforce stages. Matching is PII-heavy. Timestamps are usually delayed. Dedup against any pixel you already fired.
Google Ads enhanced conversions
Enhanced conversions send hashed first-party data with the Google Ads conversion tag or via the API. It is not GA4. It is not a replacement for gclid. It is extra matching when cookies are thin.
Conversion value and ISO 4217 currency
Purchase events need a number and a three-letter currency. USD is not a symbol. 19,99 is not a JSON number in the US. Meta, GA4, and Floodlight all refuse to optimize on empty value.
Standard vs custom events
Pinterest standard events are lowercase (pagevisit, checkout, addtocart). Meta is PascalCase (Purchase, Lead, AddToCart). Snap is UPPER_CASE. A typo becomes a custom event and still 200s.
Funnel events
Funnel events exist so the platform can optimize toward the next step. Firing all of them on the thank-you page teaches the model that every user is a buyer. Firing none of them except Purchase starves upper-funnel learning.
Refund and cancel events
If you send Purchase and never send Refund, the ads platform keeps spending toward orders that came back. Meta, GA4, and several CAPIs have refund events. Use the original transaction id.
Conversions API not working
Conversions API not working, Meta CAPI 200, Facebook CAPI empty Test Events: count event_time digits, strip test_event_code in prod, hash email not IP, match Pixel ID and event_id, and lint the JSON before you debug the token.
Conversion API validator
A conversion API validator checks CAPI JSON against the vendor contract: Meta CAPI and Facebook CAPI event_time in seconds, hashed em, action_source, event_source_url, Purchase value and currency. Paste the body. HTTP 200 is not that check.
Identity and matching
Hashing PII for CAPI
Email, phone, name, and external_id on Meta, TikTok, Snap, and Pinterest conversion APIs are SHA-256 hex digests of a normalized string. Hash those identifiers. Leave IP, user-agent, and click cookies in the clear.
Email normalization before SHA-256
Trim whitespace, lowercase the address, then SHA-256. Hashing Buyer@Example.com does not match buyer@example.com. Google Ads enhanced conversions add Gmail-specific rules. Meta, TikTok, Snap, and Pinterest hash the string you send after trim and lowercase.
Phone numbers for CAPI
Normalize the phone to digits with a country code (E.164 without spaces or a plus), then SHA-256. Hashing (650) 555-1212 never matches 16505551212. Local formats are a miss. Country code is required.
Click ids
Paid platforms join conversions on click ids: gclid, fbclid, ttclid, msclkid, li_fat_id, twclid. UTMs do not replace them. Capture on the landing URL and send them again on the conversion.
The _fbc cookie
The _fbc cookie is Meta's click cookie, built from fbclid as fb.1.timestamp.fbclid. _fbp is the browser id cookie. Send both on conversion API events as user_data.fbc and user_data.fbp. Do not paste the raw fbclid into fbc. Do not mint a fake _fbp.
Identity graphs vs your CDP
Meta, Google, and the CDPs each keep a graph you do not own. You send hashed PII, click ids, and cookies. You do not download their device graph. Matching is a payload problem, not a warehouse join you can copy.
Cross-domain tracking
Checkout on another host drops first-party cookies and often the click id. Shop.example.com does not see _fbp from www.example.com unless Domain=.example.com. Forward gclid, fbclid, and the cookies you need, or fire CAPI from the order. GA4 linker uses _gl.
Time and attribution
Attribution windows
The attribution window is a report and bidding setting on the ads platform, not a pixel parameter. Changing it rewrites history in the UI. It does not change what the tag sent. View-through and click-through are those settings, not two pixels.
Timezones and conversion event_time
Unix event_time has no timezone. Your shop, your ads account, and your warehouse each have one. Converting local checkout time as if it were UTC shifts conversions by hours and can push them across the attribution window.
Late conversion API events
Ads graphs drop conversion API events that arrive after a maximum age. Meta CAPI is about 7 days. Snap CAPI is also 7 days. LinkedIn CAPI is 90 days. GA4 MP backdates about 72 hours. Finance still needs the late sale.
View-through vs click-through attribution
Click-through credits a click. View-through credits an impression with no click, inside a (usually shorter) window. They are report settings, not two conversion tags. Mixing them in a ROAS target double-counts attention.
Last-click vs data-driven attribution
Last-click gives the conversion to the final paid click. Data-driven spreads credit across touches the platform observed. UTM last-click in GA4 is a third story. None of these is the pixel. They are models on top of the hits. Windows still apply.
Consent and privacy
TCF v2 consent strings on pixels
gdpr must be 0 or 1. gdpr=1 needs a TC String in gdpr_consent. Pixellint decodes the string. gdpr_consent=1 and gdpr_consent=true are valid base64 and still not a TC String. Core reads query string and Floodlight-style path parameters.
IAB US Privacy string
The IAB US Privacy string is a version digit plus three Y, N, or hyphen characters. Only version 1 was published. IAB Tech Lab deprecated it on 31 January 2024 in favor of GPP. Pixellint still checks the shape and always warns that the parameter is deprecated.
Google Consent Mode v2
Google Consent Mode is a gtag or GTM signal for ad_storage, analytics_storage, ad_user_data, and ad_personalization. It is not a CMP and not a TC String. Default denied, then update on choice. EEA traffic without the v2 keys is a policy problem, not a pixel syntax problem Pixellint invented.
Cookie banners vs actually blocking tags
A banner that does not wrap tags still fires pixels on first paint. Blocking means the tag does not queue until granted, or Consent Mode defaults to denied. UX copy is not a technical control. Network tab on a fresh profile is the audit, not a screenshot of the modal.
Consent parameters on the pixel
IAB signals have to land on the request the vendor sees: query or path. A CMP in the page that never expands the ad-server macro is a local-only choice. Empty values and unexpanded macros are template exemptions. Meta LDU and Google Consent Mode are separate vendor dialects.
Consent revocation on the wire
Granting consent is a request the vendor can see. Revoking it often is not. A banner that shows a new choice while Floodlight, Meta, and CAPI keep the old string is a withdraw that never left the page. Lint the hop after refuse, not only after accept.
Mobile and MMP
SKAdNetwork vs MMP
SKAdNetwork attributes iOS campaigns with a conversion value and a delayed Apple postback. It is not a click id, not an MMP device id, and not a replacement for S2S in-app events. Map values on purpose or the postback is a coin flip. Pixellint does not validate SKAN postbacks.
App install vs session vs in-app events
Install, first open, session, and in-app purchase are different MMP events. Firing purchase on first open inflates ROAS. Firing install on every session inflates CPI. Name the event the vendor catalog uses, then S2S it once. Adjust tokens are opaque. AppsFlyer eventName is a string. Branch distinguishes standard and custom endpoints.
Deferred deep links
A deferred deep link sends the user to the store, then into the app on first open with the click context. If the MMP cannot stitch the click to the install, they land on home and you lost the campaign creative's promise. Deferred is an MMP feature, not an OS feature.
Web-to-app measurement
A paid click on the web that converts in the app needs a bridge: MMP, Meta app events, or SKAN. The web pixel alone stops at the store page. Store the web click id before the user leaves for the store. action_source=app on CAPI. Do not fire website Purchase when the charge happened in IAP.
Analytics and CDP
Adobe Analytics sendBeacon
Adobe Analytics sendBeacon (and the image beacon fallback) still needs the report suite on /b/ss/. s.t() and s.tl() are different. SPA apps that never call s.t() on route change go dark after the first page. This is not a GA4 event.
CDP vs ads pixels vs product analytics
A CDP (Segment and friends) routes events. An ads pixel or CAPI is a bid and attribution pipe. Product analytics is product. One track() call is not automatically all three jobs done well.
Event volume, sampling, and pixel QA
GA4 UI sampling and Mixpanel bookkeeping hide rare broken payloads. QA on 20 events will never see the 1% of Purchases missing currency. Sample raw exports or contract-test fixtures.
GA4 DebugView, Meta Test Events, GTM preview
DebugView, Meta Test Events, and GTM preview are QA surfaces. They are not production. Leaving debug_mode on or test_event_code on trains the wrong graph, or no graph.
Product analytics vs ads conversion pixels
Product analytics wants funnels and retention. Ads pixels want matchable conversions for bidding. Sharing one Purchase event is fine. Sharing one schema without a map is how both teams think the other is wrong.
Launch and QA
PM checklist
Ship the event dictionary, owners, environments, PII rules, and the success metric before anyone pastes a snippet. A tag without a dictionary is how Purchse reaches production.
Marketer checklist
Before go-live: both pipes, shared event_id, Test Events showing matched user data, value and currency on money events, and a plan for refunds. Empty Test Events means you are not live, even if GTM says the tag fired.
QA pixels in staging
Staging must not train production. Use test_event_code, debug_mode, or a separate pixel / measurement id. Pointing staging at the production pixel because 'it is easier' is a data incident.
Debugging pixels in Chrome Network
Filter by collector host: facebook.com/tr, google-analytics.com/g/collect, ads.tiktok.com. Preserve log across redirects. Status 200 is the start of the story, not the end.
GTM loader and preview
The GTM loader is googletagmanager.com/gtm.js?id=GTM-XXXX. That request is not the conversion hit. Preview attaches a debug cookie to a draft. Users without it get the published container. Shipping on preview alone is how unpublished tags look fine.
Pixel not firing
Facebook pixel not firing, TikTok pixel not tracking, GTM says the tag fired and Network is empty. Check the collector URL, ad blockers, consent, SPA routes, duplicate installs, and GTM environments. Then paste the URL into a pixel validator.
Facebook Pixel Helper vs Network
Facebook Pixel Helper is a vendor overlay. Chrome Network is the fired facebook.com/tr URL. Events Manager is delayed. A tracking pixel validator lints that URL against Meta's documented parameters before you wait on the UI.
Vendor playbooks
Meta pixel and CAPI
Meta pixel and CAPI: fbq in the browser plus Facebook CAPI on the server, same event_name and event_id. Meta CAPI event_time in seconds. Hash em and ph. Send IP and UA in the clear. _fbp and _fbc when you have them.
TikTok Pixel and Events API
ttq in the browser plus Events API on the server. Server timestamps are ISO 8601, not Unix seconds. Hash email and phone. Do not hash IP or user-agent. Dedup with event_id.
LinkedIn Insight Tag documentation
LinkedIn insight tag documentation: the Insight Tag is an image pixel, LinkedIn CAPI is JSON with conversionHappenedAt in milliseconds. Lead gen plus a CRM upload is a third path. Do not mix the clocks.
Pinterest CAPI
Pinterest standard events are lowercase names: pagevisit, checkout, addtocart. The tag in the browser plus Conversions API on the server share event_id. Hash the PII fields Pinterest names. Catalog content ids should match the feed if you run catalog ads.
Reddit CAPI
Reddit CAPI v3 posts conversion events to ads-api.reddit.com with event_at in milliseconds and action_source in uppercase (WEBSITE, not website). The Reddit Pixel is a separate image on alb.reddit.com. Do not copy a Meta CAPI body onto Reddit CAPI.
DART Floodlight tags
DART Floodlight tags are Campaign Manager activity tags on doubleclick.net. Parameters ride as src, type, cat, plus a unique ord. DART was DoubleClick's ad server; the tags did not change. Consent macros must expand to a TC String, not to 1.
Google Ads conversion pixels and enhanced conversions
Conversion linker writes first-party cookies. The conversion tag fires on thank-you with send_to. Enhanced conversions add hashed email or phone. gclid still matters. Consent Mode still matters.