Twitter/X Pixel
The Twitter/X Pixel tracks website activity for users who click Twitter/X ads. It enables conversion optimization, audience building, and attribution for X ads campaigns. X rebranded from Twitter in 2023, but the pixel is still called “Twitter Pixel” in the ads interface—this won’t change.
Be honest upfront: X’s advertising platform has a smaller market share than Meta, Google, TikTok, and LinkedIn. If you have meaningful X ad spend, implement this. If not, deprioritize it. X’s tracking infrastructure is less mature than competitors and has experienced outages in the Conversions API. Start with client-side setup; add server-side only if you’re running sGTM for other platforms.
Prerequisites
Section titled “Prerequisites”- X Ads account with active campaigns
- Pixel ID from X Ads Manager → Conversions → Pixels (looks like
o7g7ror similar alphanumeric code) - For Conversions API: OAuth access token and authentication bearer token from X
Base pixel installation via GTM
Section titled “Base pixel installation via GTM”-
In GTM, Tags → New
-
Recommended: Search Community Template Gallery for “Twitter Pixel” or “X Pixel”
-
If a template exists and is maintained, use it. If not, follow the Custom HTML approach below.
-
Configure the base tag:
- Pixel ID: your X Pixel ID
- Fire on: All Pages trigger
-
Publish
Custom HTML installation (reliable backup):
Since X’s template support is inconsistent, here’s the native implementation:
<script>!function(e,t,n,s,u,a){e.twq||(s=e.twq=function(){s.exe?s.exe.apply(s,arguments):s.queue.push(arguments)},s.version='1.1',s.queue=[],u=t.createElement(n),u.async=!0,u.src='https://static.ads.twitter.com/uwt.js',a=t.getElementsByTagName(n)[0],a.parentNode.insertBefore(u,a))}(window,document,'script');
twq('config', '{{Pixel ID}}');</script>Replace {{Pixel ID}} with a GTM variable containing your X Pixel ID.
Important: This base code must fire on every page. Do not gate it behind consent checks on first load—X uses cookies and first-party data to track sessions, and the initialization must occur for subsequent events to fire correctly. (Consent gating happens at event level, not initialization.)
Standard events
Section titled “Standard events”X supports the following standard event names:
PageView
Section titled “PageView”Fires automatically with the base pixel code (twq('config', ...) initialization). No additional tag needed.
Purchase
Section titled “Purchase”The most critical event for conversion optimization.
Event: tw-purchaseParameters: value: {{DL - Revenue}} // number currency: {{DL - Currency}} // ISO 4217 (e.g., "USD") content_ids: [{{DL - Item IDs}}] // array of product IDs content_name: {{DL - Product Name}} content_type: "product" num_items: {{DL - Item Count}}Custom HTML tag approach:
twq('track', 'Purchase', { value: {{DL - Revenue}}, currency: '{{DL - Currency}}', content_ids: {{DL - Product IDs as Array}}, content_type: 'product', num_items: {{DL - Item Count}}});Trigger: Custom Event — purchase
AddToCart
Section titled “AddToCart”twq('track', 'AddToCart', { value: {{DL - Price}}, currency: '{{DL - Currency}}', content_ids: [{{DL - Product ID}}], content_type: 'product', num_items: {{DL - Quantity}}});Trigger: Custom Event — add_to_cart
Checkout (Begin Checkout)
Section titled “Checkout (Begin Checkout)”twq('track', 'Checkout', { value: {{DL - Cart Value}}, currency: '{{DL - Currency}}', content_ids: {{DL - Product IDs}}, num_items: {{DL - Item Count}}});Trigger: Custom Event — begin_checkout
Lead / SignUp
Section titled “Lead / SignUp”twq('track', 'SignUp', { value: {{DL - Lead Value or Fixed}}, currency: '{{DL - Currency}}'});Or for explicit lead forms:
twq('track', 'Lead', { value: {{DL - Lead Value}}, currency: '{{DL - Currency}}'});Trigger: Custom Event — signup or lead
ViewContent
Section titled “ViewContent”Fire on product detail pages to build website visitor audiences.
twq('track', 'ViewContent', { content_ids: [{{DL - Product ID}}], content_name: '{{DL - Product Name}}', content_type: 'product', value: {{DL - Price}}, currency: '{{DL - Currency}}'});Trigger: Custom Event — view_item
Search
Section titled “Search”twq('track', 'Search', { search_query: '{{DL - Search Term}}'});Trigger: Custom Event — search
Additional events
Section titled “Additional events”X also supports: AddToWishlist, Download, CompleteRegistration. These are less common but follow the same pattern—check X Ads Manager → Pixels → Event Details for full parameter lists.
Click ID (twclid) handling
Section titled “Click ID (twclid) handling”X appends a twclid URL parameter to all ad clicks (similar to fbclid for Meta). Capturing and storing this enables proper attribution.
Capture and store twclid
Section titled “Capture and store twclid”Step 1: Custom JavaScript Variable to read the parameter
In GTM, create a new Custom JavaScript Variable:
function() { var url = new URL(window.location); var twclid = url.searchParams.get('twclid'); return twclid || undefined;}Name it JS - Get twclid from URL
Step 2: Store in a first-party cookie
Create a Custom HTML tag to persist twclid in a cookie for the session:
<script>(function() { var url = new URL(window.location); var twclid = url.searchParams.get('twclid');
if (twclid) { // Store twclid in a first-party cookie for 30 days var d = new Date(); d.setTime(d.getTime() + (30 * 24 * 60 * 60 * 1000)); var expires = 'expires=' + d.toUTCString(); document.cookie = '_twclid=' + twclid + '; ' + expires + '; path=/; Secure'; }})();</script>Trigger: All Pages (high priority, before other tags)
Step 3: Read the stored cookie in GTM
Create a Cookie Variable named _twclid to retrieve it for CAPI deduplication or custom reporting.
Why this matters
Section titled “Why this matters”X uses twclid for first-party attribution. If a user clicks an X ad (twclid parameter present) but their conversion fires client-side only, X can match the click. If you’re also using sGTM + Conversions API, storing twclid ensures you can pass it server-side for additional matching.
Conversions API (server-side)
Section titled “Conversions API (server-side)”X’s Conversions API (still newer and less stable than Meta’s) allows server-to-server event transmission. It’s useful for:
- Deduplicating client-side and server-side events
- Recovering events blocked by browser restrictions
- Improving match rates with server-side hashed user data
Setup overview:
- OAuth: Generate a long-lived access token in X Ads Manager → Apps → Conversions API
- sGTM container: Create a tag using a community template (if available) or Custom JavaScript
- Event mapping: Consume GA4 events and translate to X event names (e.g.,
purchase→Purchase) - Deduplication: Include
event_idon both client-side pixel and server-side API calls
sGTM tag template (custom JavaScript approach):
const makeRequest = require('makeRequest');const crypto = require('crypto');const getAllEventData = require('getAllEventData');
let eventData = getAllEventData();
// Map GA4 event name to X event nameconst eventMap = { 'purchase': 'Purchase', 'add_to_cart': 'AddToCart', 'begin_checkout': 'Checkout', 'view_item': 'ViewContent', 'lead': 'Lead'};
let xEventName = eventMap[eventData.event_name] || null;if (!xEventName) { return data.gtmOnFailure();}
// Read parameterslet payload = { event: xEventName, event_id: eventData.event_id, // For deduplication timestamp_millis: eventData.timestamp_millis};
// Add conversion value if presentif (eventData.value) { payload.value_micros = Math.round(eventData.value * 1000000);}
if (eventData.currency) { payload.currency = eventData.currency;}
// Add user data (if available and hashed)if (eventData.user_data) { payload.user_data = {}; if (eventData.user_data.hashed_email) { payload.user_data.em = eventData.user_data.hashed_email; }}
// Add twclid if availableif (eventData.twclid) { payload.twclid = eventData.twclid;}
// Send to X Conversions APIconst headers = { 'Authorization': 'Bearer {{X API Token}}', // Store securely in GTM 'Content-Type': 'application/json'};
makeRequest( { url: 'https://analytics.twitter.com/1.1/conversion/track', method: 'POST', headers: headers, payload: JSON.stringify(payload) }, function(statusCode) { if (statusCode >= 200 && statusCode < 400) { data.gtmOnSuccess(); } else { data.gtmOnFailure(); } });Key notes:
- Replace
{{X API Token}}with a GTM Variable containing your X Conversions API bearer token - Include
event_idfor deduplication (X will match client + server events with the same ID) - Value is sent in micros (
value * 1000000), not as a decimal twclidfrom the stored cookie helps X match the click to the conversion
Deduplication behavior: If you send the same event_id from both client-side pixel and Conversions API, X counts it once. Omit event_id if you want both to be counted separately (not recommended for Purchase events).
Consent Mode
Section titled “Consent Mode”Gate the pixel on ad_storage consent using GTM’s Consent Mode or a custom consent check.
<script>// Pseudo-code: check if ad_storage is granted before initializingif (window.gtag && window.gtag.getConsent) { var consentData = window.gtag.getConsent(); if (consentData.ad_storage !== 'granted') { // Skip initialization return; }}
// If ad_storage is granted, initialize:twq('config', '{{Pixel ID}}');</script>Alternatively, in the base GTM tag configuration:
- Check “Require consent for tag to fire”
- Select
ad_storageconsent type
This prevents the pixel from firing until users grant ad_storage consent (typically via a CMP banner).
Troubleshooting
Section titled “Troubleshooting”Verify events in X Ads Manager
Section titled “Verify events in X Ads Manager”- Go to X Ads Manager → Conversions → Pixels → your Pixel
- Click “Test Conversion” (or similar option depending on UI version)
- Enter your website URL
- Trigger a conversion on your site (view a product, add to cart, make a purchase)
- Check the Ads Manager—events should appear within 1–2 minutes
X Pixel Helper Chrome extension
Section titled “X Pixel Helper Chrome extension”X provides an official X Pixel Helper extension:
- Install from Chrome Web Store
- Open DevTools (right-click → Inspect → find the X Pixel Helper panel)
- Load your website—the extension shows events fired, parameters, and errors
Common issues
Section titled “Common issues”Pixel not firing at all:
- Verify Pixel ID is correct in your GTM tag
- Check GTM tag has “All Pages” trigger
- Verify ad blocker is not blocking
static.ads.twitter.com
Events showing in Ads Manager but not attributed to campaigns:
- Verify twclid is being captured from ad clicks
- Check
currencyis a valid ISO 4217 code (e.g., “USD”, not “US”) - Ensure
valueis a number, not a string
High event volume but low attribution:
- X attributes conservatively; clicks without matching conversions are dropped silently
- Verify users are actually clicking your X ads (test with a small budget)
- Cross-check that impressions in the campaign are generating clicks
Conversions API failures (server-side):
- Verify API token is valid and not expired
- Check API endpoint is correct:
https://analytics.twitter.com/1.1/conversion/track - Monitor sGTM logs for HTTP errors (401 = auth failure, 400 = bad payload)
When to bother with X Pixel
Section titled “When to bother with X Pixel”- Do implement if you have active, profitable X advertising campaigns
- Do implement if your audience skews heavily toward tech professionals or developers (where X has stronger engagement)
- Skip if X spend is less than 5% of your total paid ad budget — focus on Meta, Google, TikTok first
- Skip if you have no X ad campaigns running—don’t implement for future use
X’s platform is smaller and its tracking infrastructure is not as battle-tested as competitors. Build your foundation with Meta and Google, then add X if ROI justifies the implementation effort.