Event Tracking

Adlocaite uses a VAST 4.0 compliant event tracking system to record ad playout progress. Instead of a single confirmation call, individual events (start, quartiles, complete) are tracked as they occur -- enabling granular reporting and accurate billing.

Overview

When a screen plays an advertisement, your player fires tracking pixels at defined points during playback. These events are ingested by the Adlocaite Tracking Service and stored per offer for reporting and billing.

OpenRTB loss notices (lurl) for SSP integrations are not handled here; they go to the OpenRTB endpoint, see Loss notifications.

Integration Flow: Request Offer → Accept Offer → Display Ad → Fire Tracking Events

Two integration paths are available:

  • VAST players (recommended) -- Request offers with vast=true. The returned VAST XML already contains all tracking pixel URLs, including the correct tracking host, publisher ID and screen ID for the environment you called. Your player fires them automatically during playback and never has to build a tracking URL itself.
  • Custom / SDK integration -- Fire tracking events yourself via HTTP, either as individual GET pixel requests or as a batch POST. Use this path only if your player cannot consume VAST. You are then responsible for the host and for the pub and scr parameters described below.

Environments

The Tracking Service runs as a separate host per environment. Events must go to the tracking host that belongs to the API host you requested the offer from.

Do not mix environments

An offer requested from the staging API only exists in staging. If your player sends its tracking events to the production tracking host, they arrive in an environment where neither the offer nor the screen is known. The events are discarded, never appear in your staging reports, and the playout cannot be matched to a deal. VAST URLs returned by the API already point to the right host; if you build URLs yourself, make the tracking host part of the same configuration as the API host.


VAST tracking events

The tracking system supports the following standard VAST events. Each event corresponds to a specific moment during ad playback:

  • Name
    impression
    Type
    event
    Description

    The ad was loaded and is about to be displayed. Fired once when the ad unit is first rendered.

  • Name
    start
    Type
    event
    Description

    Video/image playback has started (0% progress).

  • Name
    firstQuartile
    Type
    event
    Description

    Playback reached 25% of total duration.

  • Name
    midpoint
    Type
    event
    Description

    Playback reached 50% of total duration.

  • Name
    thirdQuartile
    Type
    event
    Description

    Playback reached 75% of total duration.

  • Name
    complete
    Type
    event
    Description

    Playback finished (100% of duration). This is the primary billing-relevant event.

The tracking service also accepts an error event with a code parameter for VAST 4.0 error reporting, but this is not relevant for billing.


Required events for billing

For a playout to be counted as billable, a minimum set of events must be received. This follows the VAST 3.0 minimum standard:

EventRequiredDescription
impressionRequiredMust be fired for the playout to be registered at all.
startRequiredConfirms that playback actually began.
firstQuartileRecommendedImproves reporting granularity.
midpointRecommendedImproves reporting granularity.
thirdQuartileRecommendedImproves reporting granularity.
completeRequiredMust be fired for the playout to count as billable.
Minimum for billing

At minimum, impression, start, and complete must be received for a playout to be billed. Missing any of these three events means the playout will not be counted. We strongly recommend sending all six standard events for full reporting coverage.


GET/track

Tracking via VAST pixels

When you request offers with vast=true, the returned VAST XML contains tracking pixel URLs for all standard events. A VAST-compliant player fires these URLs automatically as HTTP GET requests during playback. This is the recommended path: the URLs already carry the right host, publisher ID and screen ID.

If your player cannot consume VAST, you can build the same URLs yourself. Use the tracking host of the environment you requested the offer from and include all parameters below.

URL format

https://tracking.adlocaite.io/track?offer_id={offer_id}&event={event}&ts={timestamp}&pub={publisher_id}&scr={screen_id}

Query parameters

  • Name
    offer_id
    Type
    string
    Description

    Required. The UUID of the ad offer being tracked.

  • Name
    event
    Type
    string
    Description

    Required. Event type: impression, start, firstQuartile, midpoint, thirdQuartile, complete, or error.

  • Name
    ts
    Type
    integer
    Description

    Required. Client timestamp in Unix milliseconds. In VAST URLs it is set at generation time; when you build URLs yourself, set it to the moment the event occurred.

  • Name
    pub
    Type
    string
    Description

    Required. Publisher ID (UUID) of the screen's publisher, as provided during onboarding. Events without pub are discarded.

  • Name
    scr
    Type
    string
    Description

    Required. Screen ID (UUID) of the screen that played the ad. Must be a screen registered in the same environment and belonging to pub; events for unknown screens are discarded.

Discarded events return the same 1x1 GIF as accepted ones. They are not stored, never show up in reporting, and the playout does not count as billable. If you fire pixels yourself, verify during integration that your playouts appear in reporting with all expected events.

The endpoint returns a 1x1 transparent GIF with Cache-Control: no-store headers. No authentication is required -- VAST players cannot set custom headers, so these URLs are designed to work as fire-and-forget pixels.

VAST XML tracking section

GET
/track
<TrackingEvents>
  <Tracking event="start">
    <![CDATA[https://tracking.adlocaite.io/track
      ?offer_id=550e8400-e29b-41d4-a716-446655440000
      &event=start
      &ts=1710340000000
      &pub=pub-123-uuid
      &scr=screen-456-uuid]]>
  </Tracking>
  <Tracking event="firstQuartile">
    <![CDATA[https://tracking.adlocaite.io/track
      ?offer_id=550e8400-e29b-41d4-a716-446655440000
      &event=firstQuartile
      &ts=1710340000000
      &pub=pub-123-uuid
      &scr=screen-456-uuid]]>
  </Tracking>
  <Tracking event="midpoint">
    <![CDATA[https://tracking.adlocaite.io/track
      ?offer_id=550e8400-e29b-41d4-a716-446655440000
      &event=midpoint
      &ts=1710340000000
      &pub=pub-123-uuid
      &scr=screen-456-uuid]]>
  </Tracking>
  <Tracking event="thirdQuartile">
    <![CDATA[https://tracking.adlocaite.io/track
      ?offer_id=550e8400-e29b-41d4-a716-446655440000
      &event=thirdQuartile
      &ts=1710340000000
      &pub=pub-123-uuid
      &scr=screen-456-uuid]]>
  </Tracking>
  <Tracking event="complete">
    <![CDATA[https://tracking.adlocaite.io/track
      ?offer_id=550e8400-e29b-41d4-a716-446655440000
      &event=complete
      &ts=1710340000000
      &pub=pub-123-uuid
      &scr=screen-456-uuid]]>
  </Tracking>
</TrackingEvents>

Manual pixel request

curl "https://tracking.adlocaite.io/track?offer_id=550e8400-e29b-41d4-a716-446655440000&event=complete&ts=1710340000000&pub=pub-123-uuid&scr=screen-456-uuid"
# Returns: 1x1 transparent GIF

POST/track

Tracking via SDK batch

For custom player integrations or high-volume setups, you can submit multiple events in a single authenticated POST request.

Authentication

The POST endpoint requires HMAC-SHA256 authentication. Generate a token by signing the current Unix timestamp (milliseconds) with your tracking secret:

Authorization: Bearer {timestamp}::{hmac_sha256_hex}

Tokens are valid for 5 minutes after generation.

Request body

  • Name
    offer_id
    Type
    string
    Description

    The UUID of the ad offer. Must be a valid UUID format.

  • Name
    events
    Type
    array
    Description

    Non-empty array of event objects. Each event requires a type (string) and timestamp (ISO-8601 or Unix milliseconds).

  • Name
    publisher_id
    Type
    string
    Description

    Required. Publisher UUID. Batches without it are discarded.

  • Name
    screen_id
    Type
    string
    Description

    Required. Screen UUID. Must be registered in the same environment and belong to publisher_id; batches for unknown screens are discarded.

  • Name
    player_version
    Type
    string
    Description

    Optional. Your player software version identifier.

  • Name
    screen_resolution
    Type
    string
    Description

    Optional. Screen resolution during playback (e.g., "1920x1080").

Request

POST
/track
curl -X POST "https://tracking.adlocaite.io/track" \
  -H "Authorization: Bearer 1710340000000::a1b2c3d4e5f6..." \
  -H "Content-Type: application/json" \
  -d '{
    "offer_id": "550e8400-e29b-41d4-a716-446655440000",
    "publisher_id": "pub-123-uuid",
    "screen_id": "screen-456-uuid",
    "events": [
      { "type": "impression", "timestamp": "2026-03-13T10:00:00Z" },
      { "type": "start", "timestamp": "2026-03-13T10:00:01Z" },
      { "type": "firstQuartile", "timestamp": "2026-03-13T10:00:04Z" },
      { "type": "midpoint", "timestamp": "2026-03-13T10:00:06Z" },
      { "type": "thirdQuartile", "timestamp": "2026-03-13T10:00:09Z" },
      { "type": "complete", "timestamp": "2026-03-13T10:00:11Z" }
    ],
    "player_version": "2.1.0",
    "screen_resolution": "1920x1080"
  }'

Success response (200)

{
  "success": true,
  "event_id": "evt-a1b2c3d4-uuid",
  "events_count": 6
}

Error: invalid offer_id (400)

{
  "error": "Invalid offer_id: must be a valid UUID"
}

Error: unauthorized (401)

{
  "error": "Missing or invalid authorization token"
}

Best practices

Event timing

Fire each tracking event as close to the actual playback moment as possible. The tracking service stores both the client-provided timestamp (ts) and the server receive time (received_at), so large discrepancies between these two values may flag the playout for review.

Retry logic

  • GET pixel requests -- Fire-and-forget. If a pixel fails, the VAST standard does not require retries. However, for accurate billing, we recommend retrying failed impression, start, and complete pixels up to 3 times with exponential backoff.
  • POST batch requests -- Implement retry with backoff on 5xx responses. 4xx errors indicate a client-side issue (invalid token, malformed body) and should not be retried without fixing the request.

Offline / buffered playback

For screens with intermittent connectivity, buffer events locally and submit them via the POST batch endpoint when connectivity is restored. Include accurate client timestamps so the events can be attributed to the correct playback session.

Performance

  • Tracking pixel requests are non-blocking -- they return a 1x1 GIF immediately and process asynchronously
  • For high-volume setups with many screens, prefer the POST batch endpoint to reduce HTTP overhead
  • Set reasonable timeouts (3-5 seconds) for pixel requests to avoid blocking your content pipeline

POST/playout/confirm/{dealId}

Deprecated: playout/confirm

Deprecated -- removal after 2026-06-01

The legacy POST /playout/confirm/{dealId} endpoint is deprecated. It still works but only fires a single complete event internally and does not provide the granular tracking data needed for full billing and reporting.

Migrate to VAST tracking events or the POST /track batch endpoint.

Migration guide

The old endpoint accepted a deal_id and optional metadata. The new system tracks by offer_id and uses standard VAST events:

Old (playout/confirm)New (event tracking)
Single POST per dealMultiple events per offer
deal_id basedoffer_id based
completion_rate: 100complete event fired
played_at timestampstart event timestamp
No quartile dataFull quartile tracking
Requires API key authGET pixels: no auth / POST batch: HMAC

How to migrate

  1. VAST players: Request offers with vast=true. The VAST XML includes all tracking pixel URLs. Remove any manual playout/confirm calls.
  2. Custom players: Replace the single playout/confirm POST with individual GET pixel requests (or a POST batch) for impression, start, and complete at minimum. Always include pub and scr, and use the tracking host of the environment your API key belongs to.
  3. Verify: Check that your playouts appear in reporting with all expected events.

Old (deprecated)

# Don't use this anymore
curl -X POST "https://api.adlocaite.com/functions/v1/api/playout/confirm/DEAL_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "played_at": "2026-03-13T14:30:00Z",
    "duration_seconds": 15,
    "completion_rate": 100
  }'

New (VAST pixel -- recommended)

# Request offer with VAST
curl "https://api.adlocaite.com/functions/v1/api/offers/request/SCREEN_ID?vast=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Player automatically fires pixels from VAST XML:
# impression, start, firstQuartile, midpoint,
# thirdQuartile, complete

New (manual pixels)

# Fire events individually. pub and scr are required;
# use the tracking host of your environment (see Environments).
curl "https://tracking.adlocaite.io/track?offer_id=OFFER_ID&event=impression&ts=$(date +%s000)&pub=PUBLISHER_ID&scr=SCREEN_ID"
curl "https://tracking.adlocaite.io/track?offer_id=OFFER_ID&event=start&ts=$(date +%s000)&pub=PUBLISHER_ID&scr=SCREEN_ID"
# ... playback happens ...
curl "https://tracking.adlocaite.io/track?offer_id=OFFER_ID&event=complete&ts=$(date +%s000)&pub=PUBLISHER_ID&scr=SCREEN_ID"

Deprecation response

{
  "success": true,
  "deprecated": true,
  "message": "This endpoint is deprecated and will be removed after 2026-06-01. Playout tracking now happens automatically via VAST tracking pixels.",
  "deal_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479"
}

Was this page helpful?