Skip to content

Server-Side Conversions

Some conversions don’t happen in the browser. An inquiry only turns into a paid order days later, a subscription activates after the trial period ends, an order is only approved after a credit check.

With the server API, you report such events from your own backend to usertrax. usertrax finds the original visit again and carries over its ad attribution — gclid, fbclid, UTM parameters — onto the new event. That way the revenue lands in Google Ads and Meta on the campaign that triggered it.

  1. Save a reference when the form is submitted

    The tracker gives you the IDs of the current visit:

    const ids = window.usertrax.getTrackingIds();
    // { session_id: "…", visitor_id: "…" }

    Write session_id into a hidden form field and store the value together with the inquiry in your database:

    <form method="post" action="/inquiry">
    <input type="hidden" name="usertrax_session" id="usertrax_session" />
    <!-- other fields -->
    </form>
    <script>
    document.getElementById("usertrax_session").value =
    window.usertrax.getTrackingIds().session_id || "";
    </script>
  2. Get your server key

    In the dashboard under Domains → Settings you’ll find the server key (utx_sk_…).

    The server key is secret. It belongs exclusively in your backend — never in JavaScript, HTML, or a public repository. It is not the same value as the auth key from the tracking script.

  3. Report the conversion

    As soon as the inquiry turns into an order, your backend sends:

    Terminal-Fenster
    curl -X POST https://api.usertrax.io/api/v1/server/conversions \
    -H "X-Server-Key: utx_sk_..." \
    -H "Content-Type: application/json" \
    -d '{
    "event": "purchase",
    "event_id": "order-8123",
    "value": 2500.00,
    "currency": "EUR",
    "reference": { "session_id": "the-stored-session-id" },
    "user_data": { "email": "customer@example.com" }
    }'

    Response:

    {
    "status": "success",
    "conversion_id": 91823,
    "event_id": "order-8123",
    "attribution_source": "session"
    }

    attribution_source shows how the link was found. If it says none, usertrax couldn’t match the original visit — the conversion is still saved, but without ad attribution.

usertrax tries several paths and takes the first match:

FieldDescription
reference.session_idThe most reliable option — see above
reference.event_idThe event_id of the original conversion, e.g. your lead event
reference.visitor_idThe recognizable visitor across multiple sessions
user_data.emailMatched to an existing profile

You can also pass gclid, fbclid, and utm directly if you’ve stored them yourself. Directly passed values always take precedence over inherited ones.

For nightly reconciliation there’s a batch endpoint with up to 100 events per request:

Terminal-Fenster
curl -X POST https://api.usertrax.io/api/v1/server/conversions/batch \
-H "X-Server-Key: utx_sk_..." \
-H "Content-Type: application/json" \
-d '{
"conversions": [
{ "event": "purchase", "event_id": "order-1", "value": 1200 },
{ "event": "purchase", "event_id": "order-2", "value": 890 }
]
}'

The response reports back each item individually. A faulty record doesn’t block the rest.

FieldTypeDescription
eventstring, requiredEvent name, e.g. purchase (max. 100 characters)
event_idstringYour own id, e.g. the order number. Used for duplicate detection
valuenumberConversion value
currencystringISO code, e.g. EUR. Defaults to the domain’s currency
event_timestampstringTime in ISO 8601 format. Defaults to now. Max. 90 days in the past
labelstringFree-form label for grouping in the dashboard
reference.session_idstringSession id from getTrackingIds()
reference.event_idstringevent_id of the original conversion
reference.visitor_idstringVisitor id from getTrackingIds()
user_dataobjectemail, customer_id, phone — for profile matching and enhanced conversions
meta_dataobjectAny additional data to store with the event
gclid, fbclid, fbc, fbp, msclkid, ttclid, adcell, awc, li_fat_idstringClick ids, if you stored them yourself
utmobjectutm_source, utm_medium, utm_campaign, utm_term, utm_content
landing_pagestringEntry page of the original visit
first_touchpoint, last_touchpointstringChannel of the first and last touch
ip_address, user_agentstringIP and user agent of the original visit, not your server’s. Improves Meta matching

Every field except event is optional. Anything you leave out, usertrax fills in from the matched visit.

  • Duplicate reports are caught via event_id. Feel free to send the same order twice — the response then reads duplicate, and no second conversion is created.
  • Backdating is possible up to 90 days (event_timestamp in ISO 8601 format). usertrax rejects older events, since Google Ads and Meta would discard them anyway.
  • Existing events stay unchanged. The inquiry doesn’t get an order “rewritten” onto it — an additional event is created instead. Your funnel stays visible.
  • The endpoints are also listed in the API reference under “Server-Side Tracking”.