Prooflytics + X Ads: Ad Attribution to Closed Deals

Prooflytics + X Ads: Ad Attribution to Closed Deals

X Ads (formerly Twitter Ads) is harder to attribute than Meta or Google: twclid (X click ID) lives 7 days, the pixel loses data due to ad blockers and iOS restrictions, and native X Analytics only shows conversions within the platform. Prooflytics closes the loop: X click -> lead -> deal in CRM -> real CAC per campaign.

The problem with standard X Ads attribution

Most marketers evaluate X Ads by CTR and CPM inside X Analytics. That’s half the picture:

  • X Analytics doesn’t see what happens after the click
  • X Pixel captures a site conversion (form, purchase) but doesn’t close the loop to the CRM
  • If a lead went through SDR qualification and closed 45 days later - X Pixel doesn’t see it (7-day click window)
  • Ad blockers and iOS 14+ cut off pixel data

The result: the marketer doesn’t know which X campaign brings paying customers. They optimize for CPL - a metric that doesn’t correlate with revenue.

X Click ID: twclid

twclid is X Ads’ proprietary click ID, analogous to Google’s gclid and Meta’s fbclid. It’s passed in the URL as a query parameter on an ad click.

https://exceltic.dev/landing?twclid=2-1234567890abcdef&utm_source=twitter&utm_campaign=q2_b2b

Characteristics:

  • Lifetime: 7 days (Google - 90, Meta - 28)
  • Only available on paid clicks (not organic)
  • Unique per click

The Prooflytics Pixel captures twclid on page load and ties it to the user session.

Prooflytics + X Ads architecture

X Ad Click
    |
    v
Landing Page (Prooflytics Pixel captures twclid + utm_*)
    |
    v
CRM Lead created (Prooflytics ties twclid to lead_id)
    |
    v
Deal closed (Prooflytics receives event from CRM webhook)
    |
    v
X Conversions API <- Prooflytics sends conversion event with twclid
    |
    v
X Ads Dashboard <- sees real conversions to sales
    |
    v
Prooflytics Dashboard <- cost per closed deal per campaign/ad group

X Conversions API: server-side events

X CAPI allows sending events directly from the server, bypassing the browser. This eliminates the impact of ad blockers and cookieless browsers.

Authentication via OAuth2 (app-only):

import requests, hashlib

X_CONSUMER_KEY    = "your_consumer_key"
X_CONSUMER_SECRET = "your_consumer_secret"
X_BEARER_TOKEN    = "your_bearer_token"  # app-only, not user token
X_PIXEL_ID        = "your_pixel_id"
X_AD_ACCOUNT_ID   = "your_ad_account_id"

CAPI_BASE = f"https://ads-api.x.com/12/measurement/conversions/{X_PIXEL_ID}"

capi_session = requests.Session()
capi_session.headers.update({
    "Authorization": f"Bearer {X_BEARER_TOKEN}",
    "Content-Type":  "application/json",
})

Sending a conversion event when a deal closes:

import hashlib, time, uuid

def hash_email(email: str) -> str:
    """SHA-256 hash of lowercase trimmed email."""
    return hashlib.sha256(email.strip().lower().encode()).hexdigest()

def send_x_conversion(twclid: str, email: str, deal_value: float, deal_id: int) -> dict:
    """Send closed deal conversion to X Conversions API."""
    event = {
        "event_id":          str(uuid.uuid4()),       # for deduplication with pixel
        "event_name":        "Purchase",               # standard X event
        "conversion_time":   int(time.time() * 1000), # milliseconds
        "identifiers": [
            {"twclid": twclid} if twclid else None,
            {"hashed_email": hash_email(email)},
        ],
        "contents": [
            {
                "content_id":    f"deal_{deal_id}",
                "content_name":  "Closed Deal",
                "content_price": deal_value,
                "currency":      "EUR",
            }
        ],
        "value": deal_value,
        "currency": "EUR",
        "custom_data": {
            "crm_deal_id": str(deal_id),
        }
    }
    # Remove None from identifiers
    event["identifiers"] = [i for i in event["identifiers"] if i]

    payload = {
        "conversions": [event],
        "ad_account_id": X_AD_ACCOUNT_ID,
    }
    r = capi_session.post(CAPI_BASE, json=payload)
    r.raise_for_status()
    return r.json()

PII (email) is only sent in SHA-256 hashed form. X does not receive the actual email.

Deduplication: pixel + CAPI

If the X pixel already fired on form submission, and CAPI sends an event on deal close - these are two different events (lead capture vs closed deal). Deduplication is only needed if the same event is sent from both channels. In Prooflytics’ scheme the pixel records PageView and Lead, CAPI records Purchase - no duplicates.

If deduplication is still needed: the event_id must be the same in both the pixel and CAPI for the same event.

CAC per campaign in Prooflytics

After sending a conversion, the X Ads Dashboard updates within 24-48 hours. In Prooflytics, a more granular breakdown is available without delay:

Campaign A -> 12 closed deals -> $28,500 revenue
Cost (X Ads spend) -> $3,200
CAC -> $267 per closed deal

Campaign B -> 3 closed deals -> $7,200 revenue
Cost (X Ads spend) -> $4,100
CAC -> $1,367 per closed deal

Prooflytics pulls spend from the X Ads Reporting API (GET /12/accounts/{id}/campaigns) and joins it with deal data from the CRM.

X Ads attribution specifics

Short twclid window: 7 days. For B2B with a 30-90+ day cycle, most closed deals won’t have a twclid. Prooflytics uses twclid when available and UTM parameters as a fallback for first/last-touch attribution.

View-through attribution: X Ads supports impression attribution (not just clicks). For B2B this is less relevant - the user saw the ad but didn’t click, then came back on their own a week later. Prooflytics doesn’t account for view-through by default for B2B deals (click-based only).

X Ads and organic: X doesn’t pass twclid for organic transitions from the platform. If a user clicked an organic post - attribution via UTM.

Real case

A SaaS company was spending $6,000/month on X Ads. X Analytics showed 340 “conversions” (lead forms) and CPL of $17.6. After a month, Prooflytics closed the data loop with the CRM:

  • Of 340 leads, qualified: 42
  • Deals closed: 8
  • Real CAC from X Ads: $750
  • Comparison with Google Ads: CAC $280

Decision: reduce X Ads budget by 60%, redistribute to Google. Two months later, the company’s overall CAC dropped by 23%.

Who this is for

Companies testing X Ads as a B2B channel and wanting to understand real ROI without relying on platform analytics. Especially relevant for FinTech, DevTools, and SaaS products whose audience is active on X.

Analogous attribution for other ad platforms: Prooflytics + LinkedIn Ads, Prooflytics + Meta Ads, Prooflytics + Google Ads.

Frequently asked questions

What is X Conversions API and why is it needed when the pixel exists?

The X Pixel runs in the browser - it’s blocked by ad blockers (uBlock, Brave) and iOS App Tracking Transparency. CAPI runs on the server and is independent of browser restrictions. According to X, CAPI improves attribution accuracy by 20-30% compared to a pixel-only approach.

How does X Conversions API verify data?

Data is sent from your server via a Bearer token (app-only OAuth2). The hashed email (hashed_email) is used by X for matching with user accounts. twclid gives an exact match - email matching is needed for attribution without twclid (when the user visited without clicking an ad).

Is X Ads effective for B2B?

Depends on the niche. DevTools, FinTech, SaaS for technical teams - X (Twitter) remains an active platform. Enterprise B2B - LinkedIn is more effective. eCPM on X is significantly lower than on LinkedIn, which provides more reach at the same budget. But audience quality needs to be verified through Prooflytics by real CAC, not platform metrics.

How long does Prooflytics setup for X Ads take?

The pixel is installed in 30 minutes (one script on the site). The CAPI integration through Prooflytics is configured without code - just enter X Ads credentials. The CRM integration for passing closed deal data takes another 1 hour for Kommo or HubSpot. First data appears in the Prooflytics Dashboard within 24 hours.

Summary

Prooflytics + X Ads provides a picture that X Analytics cannot show:

  • twclid capture on click via Prooflytics Pixel
  • X CAPI: server-side events on deal close (Bearer token, OAuth2 app-only)
  • SHA-256 email hash for matching without PII
  • CAC per campaign in Prooflytics without the 7-day twclid limitation via UTM fallback

If you’re testing X Ads and want real ROI analysis - reach out to the Exceltic.dev team. We’ll configure Prooflytics for your ad account and CRM.

More articles

All →