Custom webhooks let you send conversion events (purchases, leads, sign-ups, etc.) directly to TrustData from your server, CRM, or any platform that can make HTTP requests.
Instead of relying on browser-side tracking, you POST a JSON payload to a TrustData endpoint. TrustData matches the event to a tracked session and attributes it to the correct ad campaign.
Your server → POST /webhooks/custom/{attribution_id}/{topic}
↓
TrustData matches to visitor session
↓
Attribution credit assigned to campaign
↓
Conversion forwarded to ad platforms (if enabled)
Once enabled, the endpoint URL and API key section appear.
Backend prod, Shopify prod)Keys use the format td_wh_<random>. Only the prefix is stored in TrustData; the full key cannot be recovered after creation. If lost, revoke it and generate a new one.
POST https://t.trustdata.tech/webhooks/custom/{attribution_id}/{topic}
| Path parameter | Description |
|---|---|
attribution_id | Your attribution ID from Settings → Attribution IDs |
topic | Event type — see table below |
t.trustdata.tech.| Topic | Equivalent SDK event | Description |
|---|---|---|
purchase | purchase | Completed transaction |
lead | generate_lead | Lead form submission |
signup | sign_up | Account registration |
refund | — | Order refunded |
subscription | — | Subscription started |
custom | (any name) | Custom event |
| Header | Value |
|---|---|
Authorization | Bearer td_wh_... |
Content-Type | application/json |
The webhook payload uses the same schema as the JavaScript SDK — same field names, same objects. See the Event schema for the full reference.
A minimal purchase example:
{
"conversion_id": "ORD-12345",
"value": 149.99,
"currency": "USD",
"user_data": {
"email": "[email protected]"
}
}
A complete purchase with all signals:
{
"conversion_id": "ORD-12345",
"value": 149.99,
"currency": "USD",
"tax": 12.50,
"shipping": 5.99,
"discount_code": "SUMMER20",
"user_data": {
"email": "[email protected]",
"phone": "+15551234567",
"first_name": "Jane",
"last_name": "Doe",
"address": {
"city": "New York",
"region": "NY",
"postal_code": "10001",
"country": "US"
}
},
"products": [
{
"id": "SKU123",
"name": "Widget Pro",
"quantity": 2,
"price": 49.99
}
],
"consent": {
"analytics": true,
"advertising": true
}
}
curl -X POST \
https://t.trustdata.tech/webhooks/custom/YOUR_ATTRIBUTION_ID/purchase \
-H "Authorization: Bearer td_wh_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"conversion_id": "ORD-12345",
"value": 149.99,
"currency": "USD",
"user_data": {
"email": "[email protected]",
"phone": "+15551234567"
},
"consent": { "analytics": true, "advertising": true }
}'
curl -X POST \
https://t.trustdata.tech/webhooks/custom/YOUR_ATTRIBUTION_ID/lead \
-H "Authorization: Bearer td_wh_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"conversion_id": "lead_abc789",
"value": 50,
"currency": "USD",
"lead_type": "demo_request",
"user_data": {
"email": "[email protected]"
},
"consent": { "analytics": true, "advertising": true }
}'
TrustData links the incoming webhook to a browser session it has already tracked. The session match is what ties the conversion back to the ad click that drove it.
Matching uses visitor_id — the anonymous ID the JavaScript SDK assigns to the visitor. Pass it from your frontend to your backend when a conversion occurs.
// Frontend: get the visitor ID at checkout
const visitorId = trustdata.getVisitorId();
// Pass visitorId to your backend with the order
{
"conversion_id": "ORD-12345",
"visitor_id": "the-id-from-getVisitorId",
"value": 149.99,
"currency": "USD"
}
user_data (email, phone, etc.) is used for enhanced conversion forwarding to ad platforms — not for session matching.
If a match is found (session_matched: true in the audit log), the conversion is attributed to the campaign and forwarded to ad platforms.
The Recent Activity section in the Webhooks tab shows the last 20 requests:
| Column | Description |
|---|---|
| Status | success, auth_error, validation_error, rate_limited |
| Topic | The event topic you sent |
| Session matched | Whether TrustData linked the event to a known visitor |
Default limit: 60 requests per minute per API key. Adjustable per key in the dashboard.
401 UnauthorizedAuthorization: Bearer td_wh_...404 Not Found429 Too Many Requestssession_matched is false, the webhook was received but not linked to a visitorvisitor_id is included — it is the primary matching signal (use trustdata.getVisitorId())