Custom webhooks let you send conversion events (purchases, leads, sign-ups) 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.
Once enabled, the endpoint URL and API key section appear.
Backend prod, Shopify prod)Keys use the format td_wh_<random>. TrustData stores only the key prefix. The full key cannot be recovered after creation. If you lose the key, 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 | n/a | Order refunded |
subscription | n/a | 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, with the same field names and the 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"
}
TrustData uses user_data (email, phone) for enhanced conversion forwarding to ad platforms, not for session matching.
When TrustData finds a match (session_matched: true in the audit log), it attributes the conversion to the campaign and forwards it 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. Adjust the limit per key in the dashboard.
401 UnauthorizedAuthorization: Bearer td_wh_...404 Not Found429 Too Many Requestssession_matched is false, TrustData received the webhook but did not link it to a visitorvisitor_id, the primary matching signal (use trustdata.getVisitorId())