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.
Integration Flow: Request Offer → Accept Offer → Display Ad → Fire Tracking Events
Two integration paths are available:
- VAST players -- Request offers with
vast=true. The returned VAST XML already contains all tracking pixel URLs. Your player fires them automatically during playback. - Custom / SDK integration -- Fire tracking events yourself via HTTP, either as individual GET pixel requests or as a batch POST.
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:
| Event | Required | Description |
|---|---|---|
| impression | Required | Must be fired for the playout to be registered at all. |
| start | Required | Confirms that playback actually began. |
| firstQuartile | Recommended | Improves reporting granularity. |
| midpoint | Recommended | Improves reporting granularity. |
| thirdQuartile | Recommended | Improves reporting granularity. |
| complete | Required | Must be fired for the playout to count as billable. |
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.
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.
URL format
https://tracking.adlocaite.com/track?offer_id={offer_id}&event={event}&ts={timestamp}&pub={publisher_id}&scr={screen_id}
Query parameters
- Name
offer_id- Type
- string
- Description
The UUID of the ad offer being tracked.
- Name
event- Type
- string
- Description
Event type:
impression,start,firstQuartile,midpoint,thirdQuartile,complete, orerror.
- Name
ts- Type
- integer
- Description
Client timestamp in Unix milliseconds. Automatically included in VAST URLs at generation time.
- Name
pub- Type
- string
- Description
Publisher ID (UUID). Automatically included if available.
- Name
scr- Type
- string
- Description
Screen ID (UUID). Automatically included if available.
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
<TrackingEvents>
<Tracking event="start">
<![CDATA[https://tracking.adlocaite.com/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.com/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.com/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.com/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.com/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.com/track?offer_id=550e8400-e29b-41d4-a716-446655440000&event=complete&ts=1710340000000&pub=pub-123-uuid&scr=screen-456-uuid"
# Returns: 1x1 transparent GIF
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) andtimestamp(ISO-8601 or Unix milliseconds).
- Name
publisher_id- Type
- string
- Description
Optional. Publisher UUID.
- Name
screen_id- Type
- string
- Description
Optional. Screen UUID.
- 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
curl -X POST "https://tracking.adlocaite.com/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, andcompletepixels 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
Deprecated: playout/confirm
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.
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 deal | Multiple events per offer |
deal_id based | offer_id based |
completion_rate: 100 | complete event fired |
played_at timestamp | start event timestamp |
| No quartile data | Full quartile tracking |
| Requires API key auth | GET pixels: no auth / POST batch: HMAC |
How to migrate
- VAST players: Request offers with
vast=true. The VAST XML includes all tracking pixel URLs. Remove any manualplayout/confirmcalls. - Custom players: Replace the single
playout/confirmPOST with individual GET pixel requests (or a POST batch) forimpression,start, andcompleteat minimum. - 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
curl "https://tracking.adlocaite.com/track?offer_id=OFFER_ID&event=impression&ts=$(date +%s000)"
curl "https://tracking.adlocaite.com/track?offer_id=OFFER_ID&event=start&ts=$(date +%s000)"
# ... playback happens ...
curl "https://tracking.adlocaite.com/track?offer_id=OFFER_ID&event=complete&ts=$(date +%s000)"
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"
}