AdTech Integration Guides

AdTech Integration Guides

  • App (SDK)
  • App (Somquery)
  • Desktop
  • CTV

›Version 1.0

Overview

  • Introduction

Version 1.0

  • Integration Guide

Deprecated

  • Introduction
  • AdLayer Managers

ctv-Somtag Integration Guide

Resources and Actors

The somtag library implements the interface for TV clients due to ad operation purpose. It is not a rendering engine. Its purpose is exposing an api that is meant to:

  • Create an ad url based on a set of input parameters in order to target different ad server implementations.
  • Interpret a mapping file to map input parameters from the application to output parameter for the ad url.
  • Interpret a mapping file to declare the maximum available ad slots and positions for the application.
  • Submit ad requests and evaluate their ad responses.
  • The signature of ad responses is varying. For convenience, it unifies the responses to a more general format.
  • Shares methods to operate on a single ad data object, like submitting tracking requests.
  • It does not call an ad server directly. A request is always proxied by another server instance (somquery). somtag has a strong contract to the AdProxy.

The mapping files reflect the structure of a page, application or any kind of content. They are responsible to map those taxonomies to any ad server parameters. A mapping file is explicitly designed for a use case and the responsibility for creating and maintenance lays with the ad management team.

In the common approach you add one particular mapping to your application. Nevertheless, if your environment is more complex, it is possible to embed multiple mappings to distribute the use cases over multiple files (and even to change them dynamically).

somquery is not a resource to load, but an important actor in the system. It is the "man in the middle" between somtag and an ad server to target, due to:

  • Legal requirements in respect to end user privacy
  • Device limitations, to improve performance and prevent quirks

Paths

somtag //ad.71i.de/ctv/somtag/{VERSION}/index.js

mapping file(s) //ad.71i.de/ctv/mapping/{VERSION}/my-use-case.js

somquery

  • Dev Environment //dev-adproxy.eu-central-1.elasticbeanstalk.com
  • Stage Environment //stage-adproxy.eu-central-1.elasticbeanstalk.com
  • Prod Environment //adproxy.eu-central-1.elasticbeanstalk.com (alias ctv.71i.de)

Version Control

For resources we follow the best practices of semantic version in the form vMAJOR.MINOR.PATCH-QUALIFIER. You can target somtag or mapping files on any level of the version string.

  • Defining the major version only, eg v1, allows incremental feature development and bug-fixing without any update on publisher side. Only breaking changes are prohibited.
  • Defining the major and minor version, eg v1.2, allows bug-fixing only without any update on publisher side.
  • Defining the major, minor and patch version, eg v1.2.1, requires updates on publisher side consequently on a bug-fixing level.
  • The qualifier - mostly alpha, beta, rc - is also a very strict definition like the patch version, but follows a different deployment logic. Where deployments without a qualifier will create a new folder for x.x.x and update the files of x.x and x, deployments with a qualifier just creating a new folder.

API

Somtag

The somtag api is exposed on the top level window object.

config(taxonomy: Taxonomy = {}, options: Options = {}): Somtag

Is meant to be called exactly one time after somtag is loaded. It allows for the most static parameters or default values that are not going to change (often) over multiple content views to be defined.

somtag.config(
  { brand: 'pro7' },
  { proxyUrl: 'http://ctv.71i.de' }
);

See Taxonomy and Options for more details.

info: String

Used to request build information, where version represents the actual version, build is debug or prod and date shares the creation time.

console.log(somtag.info);
// `${version}-${build} | ${date}`

init(taxonomy: Taxonomy = {}, options: Options = {}): Promise(LifecycleContext)

Can be called multiple times. When the content in an application changes in a way, that new ads (same slot) can be received, the taxonomy has changed and a new lifecycle should be initiated.

It allows to define the most dynamic parameters or to override default values that are going to change over multiple content views.

somtag.init(
  { clipId: '12345' },
  { mappingFileId: 'videocenter' }
);

See Taxonomy and Options for more details.

LifecycleContext

This is the last chance to setup somtag more precisely before starting the ad machine. One of the reasons can be ad midroll scheduling.

At the moment, this is just a defensive look into the future, to have a hook for the publisher in place before lifecycle runtime.

Before calling start, no request will be made, no logic will be processed ... it is all about configuration so far.

start(): Promise(LifecycleRuntime)

Start a lifecycle / content view.

(If allowed), somtag is going to request 3rd party vendors, in terms of targeting etc. After completion, the lifecycle is fully configured and ready to target ads.

LifecycleRuntime

The api to use during a lifecycle / content view to enhance ad experience.

dispose(): void

Kill a lifecycle instance, to prevent memory leaks.

process(ad: Ad): AdProcessor

Creates a controller to operate on an Ad interface.

query(slot: String, index: Int = 1 | callback: Function = undefined, callback: Function = undefined): Promise([...Ad])

Request a list of ads.

The slot defines a phase in your content view, where you want to receive specific ad products. There is no technical limitation about ad slot names, but a convention exist.

Common slot names:

  • preroll
  • midroll
  • postroll

Behind an ad slot, a list of ad positions are defined. They are defined by a related mapping file. The golden rule: A publisher performs requests on a slot level and ad management enriches these slots with positions based on the given taxonomy.

The index is only required for repeating slots, like the midroll slot.

The callback argument can be used to increase the user experience. When calling somtag.query, all ad positions have to be resolved before the Promise can resolve. Sometimes this may take too long.

In order to avoid too much latency, you can use the callback function to receive a notification when the next position is resolved. This will allow you to start playback in parallel to the ongoing request phase.

lifecycle
  .query('midroll', 2, ads => {
    if (ads.length === 1) {
      // start playing first ad
    }
  })
  .then(ads => {
    ads.shift();
    // wait for first ad to complete
    // and start playing all other ads
  })

Keep in mind, somtag technically does not prevent you from requesting the same slot twice or multiple slots with the same index. However, this is not best practice. For example, when you request a preroll you must process every ad that is returned whether it is playable or not (in terms of tracking).

AdProcessor

A controller to operate on the Ad interface.

track(event: String): void

Submits all tracking requests for the given event type.

The types of events are aligned with the IAB VAST SPECS

lifecycle
  .query('preroll')
  .then(ads => {
    const ad = lifecycle.process(ads.shift());
    ad.track('impression');
  })

Interfaces

Options

Options are affecting somtag only. They are in charge over the behaviour of somtag.

An option is a simple key-value pair and is applied on a static somtag.config and dynamic somtag.init configuration levels.

logLevel: String = 'silent'

Controls the log output of a somtag instance. Possible values are:

  • trace
  • info
  • warn
  • error
  • fatal

The log level can also become defined as query parameter of location.href. If both are defined, options from the somtag api takes precedence.

mappingFileId: String = undefined

Only required when multiple mapping files are loaded. With this option, you can control which mapping to use in a lifecycle. Commonly used in somtag.init.

The id is defined within the loaded mapping file as the id parameter.

proxyUrl: String

Defines the baseUrl to an AdProxy that implements the interface of somquery. Commonly defined in somtag.config.

For 1st Party Cookie support, you may require a CNAME entry!

Taxonomy

Can be defined on static somtag.config and dynamic somtag.init configuration level.

Taxonomies affects mapping only. They are driven as input values for a mapping file to produce an ad url.

Each individual use case of a mapping file can to be launched from here. Checkout the mapping file docs

mapping file docs

showroom:String = undefined

Activate a demo campaign (level2) for testing purpose.

The showroom can also be defined as query parameter of location.href. If both are defined, options from the somtag api takes precedence.

subsite:String = undefined

Activate a demo campaign (level1) for testing purpose.

The subsite can also be defined as query parameter of location.href. If both are defined, options from the somtag api takes precedence.

Ad

Describes the interface of an ad as an output of somtag.query. It uniforms the spectrum of possible ad responses.

Whenever a new standard is established, or a new ad product is introduced, it directly affects the integration on the publisher host application. To prevent the impact, all possible shapes are transformed to a single format.

That does not mean, that it wouldn't be possible to interact with the original interface. somquery shares a graphql interface with a zoo of accessors. We can simply add a new getter or enable a different kind of return value by endpoint along with a new somtag method.

So far, an Ad looks like:

debug: Array

Can be enabled with option logLevel. It delivers additional details about the server-side processing in somquery.

It is an array, because each ad position can follow redirects to 3rd party ad servers. It is resolved on the server, to prevent unnecessary client-server ping-pong. The number of requests and latency become reduced.

body: String

The original ad server response.

latency: Int

The response time of an ad server in msec.

reqHeaders: Array<[key, value]>

The headers that were send to an ad server.

resHeaders: Array<[key, value]>

The headers that were received from an ad server.

url: String

The final url request that is send to the ad server.

event: Array

A list of events to track on different circumstances. Events follows the IAB VAST Standard

The processor lifecycle.process(ad).track(...) operates on this data.

TODO, for some event types a publisher can provide additional information to replace url macros, eg error codes, view time spend etc.

offset: String

An IAB standard evolution, where ad progress can be tracked in a better way, besides ordinary quartile tracking.

type: String

Describes the condition, when to submit a tracking request.

url: String

Url to track.

fallback: Boolean

Declares the delivered ad as not able to render. With fallback=false this would lead to error tracking and with fallback=true this would lead to impression tracking.

format: String

The original format of the ad.

At the moment this is version/evolution of the type property, like 2.0, 3.0 etc. For sure, this is going to change, in order to offer the publisher a chance to know about the capabilities of an ad.

id: String

The campaign identifier in the adserver or a list of identifiers separated by a delimiter, when multiple ad servers were involved.

media: Array

A list of resources to load and render. Media items are designed for multi-environment delivery. A publisher needs to filter them for the best fit.

type: String

Mime-Type of the Resource.

url: String

Path of the Resource.

offset: String

If an multi ad response (VMAP) is used, the offset acting as a hint when the ad should be display, eg. midrolls.

position: String

The requested position from the mapping file.

Alternatively, the position could also become delivered from an ad server when taking VMAP into account. A mapping file would only define one url per slot and a list of ads (positions) is received from an ad server response.

slot: String

The requested slot from the publisher.

Alternatively, the slot could also become delivered from an ad server when taking VMAP into account. A publisher would only perform somtag.start and the rest of the implementation is handled by the ad server.

type: String

The original type of the ad.

At the moment this is VAST or proprietary types like switchIn. For sure, this is going to change, in order to offer the publisher a chance to decide about the correct placement to render.

Cookies

There are four cookie keys that are used to store a unique ID and comply with privacy requirements.

ad-tracking: on or off

To respect end user privacy this cookie controls user tracking. By default, a user is fully tracked. If set to true, an ad request is still possible, but with limitations regarding targeting etc. If the cookie is not set or has any other value than off it is interpreted as on.

71uuid: String

A unique user ID for tracking purposes. If this cookie is not set, a new ID is created by somtag that expires in 7 years.

This ID is only used when ad-tracking = on

anon-uuid: String

A unique tracking ID that is created by somtag and stored for 6 months in case of ad-tracking = off. If the end user switches to ad-tracking = on again, this cookie is removed.

sid: String

A unique Session-ID that is created by somtag and stored for 2 hours in case of ad-tracking = off. If the end user switches to ad-tracking = on again, this cookie is removed.

FAQ

Why is the Lifecycle API split into Context and Runtime?

In a nutshell, otherwise we always have to check if a Context was started before calling methods from Runtime.

← IntroductionIntroduction →
  • Resources and Actors
  • Paths
  • Version Control
  • API
    • Somtag
    • LifecycleContext
    • LifecycleRuntime
    • AdProcessor
  • Interfaces
    • Options
    • Taxonomy
    • Ad
  • Cookies
  • FAQ
AdTech Integration Guides
Guides
AppDesktopCTV
More
GitHub
Contact

SevenOne Media GmbH
Medienallee 4
85774 Unterföhring

71.adtechnology@gmail.com
SevenOne Media - Wir bewegen Marken
Copyright © 2023 SevenOne Media GmbH