Collector API

The Collector receives data sent from web plugins, native sdks or custom integrations and forwards it to our backend processing systems.

The following sections describe how you can create a custom integration script to communicate with the Watching That Collector.

wt cloud


Requests to the Collector endpoint must all be sent with an authorization header that looks like:

X-Api-Key: <apiKey>

You can find your api key in your Watching That account.

Failing to set this header or setting it to an invalid value will make the API respond with a 401 Unauthorized http code and the payload of the message will be discarded.


Depending on where you're sending the data from (a server environment for SSAI for example or browser/native), you may use one of the following endpoints:

  • POST
  • POST

Note: We will change the latter endpoint domain periodically to prevent it being blocked by ad blockers. For server environments we suggest you use the former one as it will always run from the same domain.

These endpoints are expecting data in JSON format as an array of objects. Each object should represent an event that happens during the lifecycle of a video (including its ads). The list of fields from each object can be found in the JSON payload fields section below. The data must be sent with a application/json content type: Content-Type: application/json.

The general JSON payload of a POST call:

    { <event 1 field1>: <value>, <event 1 field2>: <value>, ... },
    { <event 2 field1>: <value>, <event 2 field2>: <value>, ... }



curl -X POST \
  '' \
  -H 'Content-Type: application/json' \
  -H 'X-Api-Key: 12345' \
  -d '[ { "type": "init", "rid": "123-abc", "cst": 0 }, { "type": "play", "rid": "123-abc", "cst": 1000 } ]'


const data = JSON.stringify([
  { type: "init", rid: "123-abc", cst: 0 },
  { type: "play", rid: "123-abc", cst: 1000 }
const xhr = new XMLHttpRequest();

xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function() {
  if (this.readyState === 4) {
});"POST", "");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.setRequestHeader("X-Api-Key", "12345");



import requests

url = ""
payload = "[
  { \"type\": \"init\", \"rid\": \"123-abc\", \"cst\": 0 },
  { \"type\": \"play\", \"rid\": \"123-abc\", \"cst\": 1000 }
headers = {
  'Content-Type': "application/json",
  'X-Api-Key': "12345",

response = requests.request("POST", url, data=payload, headers=headers)



Before showing you the list of fields you can send to our endpoints, we should explain a few concepts that make our platform tick:


To be able to group related events together and have a clear picture of what happens during the lifecycle of a video, we have the concept of "sessions". A session represents the interval from when the video player initialises, goes through playing the video (including any potential preroll/midroll ads), until the video ends (including any postroll ad).


In case your video player is set up to go through a playlist, once a session has ended, another one should be started for the next video.

A session is identified by the rid field: all the events that belong to the same session should have the same rid. It is your responsibility to create a unique rid at the beginning of each session and send it to our endpoint along with the rest of the data.

Note that rid is a required field.

  { "type": "init", "rid": "abc123" },
  { "type": "play", "rid": "abc123" },
  { "type": "imp", "rid": "foobar-qqq" }

In the example above the first 2 events belong to a session while the third one belongs to another session.

The actual content of the rid field is not important, as long as it is reasonably unique in time. In our plugins we create rid from the current ms timestamp plus a random short string but you can use any uuid-like string.

Note: if you are sending data from both server side (SSAI for example) and client side (browser/phone/tv), make sure you're using the same rid in both contexts so we can group all the events of a session together.

Client Session Time

Once a session has started, events will start occuring at various times during the life of the session. It is important to know the order the events occurred in as well as the time they occured at as this can give us a lot of hints about things that might go wrong (or well) with a session. The actual timestamp of the event is unimportant and unreliable because of potentially misconfigured clocks on user devices. That's why we use "milliseconds since session start".

The client session time is identified by the cst field.

Note that cst is a required field

You will have to initialise a variable to the current timestamp for the init event and then, for each event, you should send the diff between the now-current time and the time of the init in the cst field:

// during init
const startTime =;

// for each event, including init:
const eventPayload = { cst: - startTime }; // plus any other fields for the event


The type field identifies what sort of event is being sent. See the Event Types table below for a list of the types we support. If the event is an init, send type: 'init', if the event is an impression, send type: 'imp', etc.

Note that type is a required field for all events but you may omit it if you're sending just environmental data that's not related to an actual event (like the browser user agent, screen size, player id, etc).

Event fields

This is the complete list of fields an event might have. It's not necessary for all events to have all fields but it would be good if each field appeared at least once in a session. For example, pu (the page url) can appear just once, say, with the init event.

Field Type Required Possible Values Description
type string yes for events init, play, ... The event type. See below for the meaning of each of these values.
st string The event subtype. Sometimes the type might be too general. Use a subtype to better segment this event.
adType string PREROLL, MIDROLL, POSTROLL The position of the ad in the session
rid string yes Request ID - unique video session ID that starts from the first event in a video (init) and lasts until the last POSTROLL finishes
streamId string The ID for the video stream supplied by the IMA DAI SDK
cst int yes Relative time of the event from init (init should have cst=0)
originalAdURL string Ad Tag Url before macro replacements
adURL string Ad Tag Url after macro replacements
pu string Page Url - the page where this event happened
adMU string Ad Media Url - the url of the video file for the ad.
adTech string html5, flash Ad Tech used in the player
src string A short code to identify the app or plugin sending events. Currently using bcp for "Brightcove plugin", jwp for "JW plugin"
v string The version of the app/plugin defined by the src field
aBl int -1, 0, 1 Whether an Ad Blocker was detected or not. Use -1 for undetermined
idx int If the video is part of a playlist, this is the index of the video in that playlist. Starts at 1.
err string yes if type is error Outer error code. For example 900
err2 string Inner Error Code. Sometimes err is too generic and might represent a group of errors. In this case err2 can be used for more context. We use it for the error code coming from ima3
debug string Extra data you might want to send with the event that should help you find clusters of data in our app
per int The in-view percentage of the player at the time of event
ww int Browser Window Width
wh int Browser Window Height
fif int 0, 1 Friendly Iframe - whether the iframe of the player allows communication with the rest of the page
w int Player width
h int Player height
adId string Ad ID
adSys string Ad System
adAN string Ad Advertiser Name
adDID string Ad Deal Id
adWId string Wrapper Ad Ids
adWSys string Wrapper Ad Systems
adCId string AD: Creative Id
adWCId string AD: Wrapper Creative Id
playerId string The unique code/name you are using for this player. Useful to group data by player
mediaId string The unique code/name you are using for the video of the current session. Useful to group data by video
pageTags string A list of comma delimited tags relevant for this video
country string UK, US, DE, ... 2 letter country code for the country of the user watching the ad/video. If you are sending the event from the browser, from the page where the event happened, you may skip this as we'll infer it from the server logs.
ip string The IP address of the user watching the ad/video. This is only used to resolve the country of the user and then removed from our servers. If you're sending the country already, you don't need to send this. If you are sending the event from the browser, from the page where the event happened, you may skip this as we'll infer it from the server logs.
browser string The name of the browser the user is using. If you are sending the event from the browser, from the page where the event happened, you may skip this as we'll infer it from the server logs.
os string The name of the operating system the user is using. If you are sending the event from the browser, from the page where the event happened, you may skip this as we'll infer it from the server logs.
device string The name of the device the user is using. If you are sending the event from the browser, from the page where the event happened, you may skip this as we'll infer it from the server logs.
deviceType string desktop, phone, tablet, tv The type of device the user is using.
autoplay boolean Is this player autoplaying?

Event Types

During a session, one or more of the following event types might be sent. Note that some events, like the errors, for example, might appear multiple times in a session.

Value Description
init This marks the start of a session. Use this event to send various data that doesn't need to be repeated for every event. pu, src, v, idx and others are values that don't change during a session and can be safely sent just once here
play Video Play event. Sent either when the player starts autoplaying or when the user clicks on the play button.
serve Send this when an ad is requested. You should know the ad tag url by now so that should be sent here.
al Ad Loaded event
sa Ad Started event
imp Impression event
efq Ad First Quartile event
esq Ad Second Quartile (midpoint) event
etq Ad Third Quartile event
ecp Ad Complete event
skip Skip ad event
vready Video Ready, loaded in the player and ready to be interacted with. In a Brightcove player, this is the video_impression event.
vview Video View event, recorded when a video is considered to be viewed. It might be the same as c0 but it doesn't have to be. In a Brightcove player, this is the video_view event.
error Error event
c0 Content started playing event
c25 Content First Quartile event
c50 Content Second Quartile (midpoint) event
c75 Content Third Quartile event
c95 Content reached 95% playthrough