Operating offline
Offline mode lets a device keep playing when it loses connectivity. The player pre-fetches a full eligible playlist while online, stores it with its creatives, and rotates locally, buffering every playback event to drain on reconnect.
Offline mode is also how the player caches media files ahead of time. Because a pre-fetch downloads each ad’s <MediaFile> bytes to local storage, those creatives are already on the device when they are needed — so the player never has to fetch a large creative at slot time, even for online playback. Pre-caching this way avoids the slot-time download that could otherwise overrun the slot and time out (see Warm a fresh player).
Pre-fetch and warm
Section titled “Pre-fetch and warm”Ahead of any outage, request the playlist with offline=true and download each ad’s creative bytes:
GET /v1alpha2/ads?playerid=screen-7&key=retailer-acme&limit=20&offline=true→ 200 OK with up to the server-side cap of ads (no dvactid).An offline ad plays only if its creative is already on the device, so download the <MediaFile> bytes at pre-fetch time, not lazily at slot time. A fresh player has an empty playlist, so run this pre-fetch on first boot before serving anything, and refresh it before stored ads approach their expires_at.
Every ad in an offline playlist is already eligible for this player and place: the server has applied location, zone, campaign eligibility, budget, and pacing before returning it. The player’s job offline is narrower: drop expired ads, match audience locally, and honor the source mix.
Choosing a stored ad
Section titled “Choosing a stored ad”At slot time: drop ads past expires_at, then rotate the rest, honoring the player’s source mix.
Online vs offline is the line that matters. Online, the server splits plays across sources per opportunity; matching the deployment’s per-source percentages is fully Verve’s job. Offline, that responsibility is the player’s: over the offline window the player keeps each source’s plays near its target share.
Honoring the source mix offline. The player already holds the per-source percentages; they are the player’s deployment’s configuration. Each ad tells the player which source it came from, via source_id (with source for the coarse type). Group the player’s eligible ads by source_id and rotate so that over the offline window each source’s plays approach its configured share. If a source has no eligible ads it can’t take its share, so renormalize its portion across the sources the player does have.
Matching audience offline
Section titled “Matching audience offline”Some stored ads carry an audience block in their verve-metadata: the flight’s dynamic targeting for the player to match locally. Play an ad when its audience matches the player’s current context (detected shoppers, cart contents, weather). An ad with no audience block targets everyone, so it is always eligible.
The block is a list of targeting_groups. An ad matches when any one group matches (groups are OR’d), and a group matches when all of its conditions match (conditions are AND’d). Each condition is one of:
| Condition | Matches when |
|---|---|
demographic |
A detected shopper fits any listed profiles entry (gender, age_range, and/or group_size). |
device |
The shopper’s basket contains one of the listed skus or items. |
store |
The current weather is one of the listed weather_types. |
frequency_cap |
The ad has not yet reached its play limit for this player. The player tracks plays locally and stops matching the ad once it has been shown max_impressions times within the cap’s window (e.g. per hour or per day). |
Play the ads whose audience matches the current context, then apply the source-mix rotation to that matching set. Enum values (gender, age range, weather) arrive as their platform string names, e.g. GENDER_FEMALE, WEATHER_TYPE_RAINY.
The same gender / age_range values here are the IAB-normalized result of whatever the device reported; see Demographics for how the online seg parameter carries the equivalent live signal.
Operating offline at scale
Section titled “Operating offline at scale”- Clock drift. Every stamped URL carries
sts(the server’s clock at decision time). Because the player replays it verbatim, the server estimates the player’s device’s drift per event: no action on the player’s side, and the player’s rawetsis always preserved. - Late events are accepted, not rejected. A fire that arrives after its campaign’s billing window has closed is still accepted (flagged server-side), so a long-offline drain never silently loses events.
- Reconnect stampede. When a whole site reconnects at once, add a short randomized delay before the player’s first drain and honor
Retry-Afteron429. - Bounded buffer. Hold roughly the offline-playlist window of events and drop oldest-first on overflow, so a long-offline device degrades to best-effort rather than unbounded growth.
For how to buffer and replay the fires themselves, see Reporting exposure.