ContentDB
ContentDB is a versatile data store that can be used to store content metadata, which can then be leveraged for context-based targeting. It can also be used to activate dynamic copy with macros.
Overview
ContentDB is a server-side database that:
- Speeds up ad request times when incorporating metadata you already store
- Allows you to store metadata for contextual targeting
- Lets you tailor ad content in real-time to the user (dynamic ad copy)
- Cuts down on mobile/app bandwidth usage when making an ad request
#1 - Speeding Up Ad Request Time
This can be confusing, so let's take an example of Prometheus, a music streaming competitor to Pandora. Prometheus has an ad platform that enables advertisers to target by genre. They also have metadata in their database tied to every song that gets played, such as:
**Song 1234:**
title: Somebody To Love
artist: Queen
genres: Classic Rock, Electric Guitar
and
**Song 6759:**
title: Like a Rolling Stone
artist: Bob Dylan
genres: Folk Rock, Acoustic Guitar
Now, in order to enable genre targeting, Prometheus has to send the genre(s) with every ad request and then set up campaigns targeting those genres. This can be done in one of two ways:
Slow Way | Fast Way |
---|---|
Every time a song gets played, Prometheus checks the Song's ID with their internal database, grabs the metadata, and passes that in the ad request to Kevel. | When integrating with Kevel, Prometheus uploads their metadata straight to Kevel's ContentDB, and later in the ad request passes just the Song ID. Now, there's no need for Prometheus to look in their database before every ad call, as Kevel will do that work. |
Therefore, by using ContentDB, Prometheus can still do genre targeting, but greatly speed up the ad request process, improving the user experience.
#2 - Storing Metadata for Contextual Targeting
Many brands use tools for analyzing page content, which can be useful for contextual targeting. For instance, let's take the fictional example of StoryTime, a site full of user-generated stories for children.
StoryTime has over 500,000 individual stories, and they would love to offer targeting by genres/themes/other attributes, like, "Nighttime Stories", "Fairy Tales", "1st-Grade-Reading-Level".
However, going through 500K stories and identifying their themes is not feasible. So they use a 3rd-party tool that uses an algorithm to identify the story's theme/genre.
StoryTime can then integrate these results with ContentDB, something like:
Schema: Stories
**Stories 1234:**
title: Mr. Bear Visits Hollywood
writer: Johnny Haverton
themes: Animals, Comical, 5th-Grade Reading Level
and
**Stories 6759:**
title: Sleepytime for Little Jimmy
writer: Meredith Jones
themes: Nighttime, Lullaby, Kindergarten-Reading-Level
Given that this data is now in ContentDB, StoryTime can use Custom Targeting to set up campaigns that target just, say, stories involving "Animals".
#3 - Incorporating Dynamic Ad Copy
Going back to the Prometheus example, with ContentDB an advertiser could set up a macro that dynamically pulls in the artist's name to be displayed in the ad copy. This means that rather than setting up thousands of ads for each artist with static text, they can create one ad that dynamically inputs the artist name.
For instance, Fender could have dynamic ad copy of "Like {{artist}}? Then you'll love our guitars!". Then, if a user is listening to a Scorpion song, it would say, "Like Scorpion? Then you'll love our guitars!". But if it's a Queen song, it'll populate with "Queen".
These dynamic macros pull from a given contentKey
JSON object that is stored in ContentDB. See below for how to set that up.
#4 - Decreasing Amount of Mobile Bandwidth, Data, and Battery Needed
One benefit of ContentDB is that by storing data server-side, in the ad request you only have to send, say, storyid: 123
, versus sending over a lot more information in the request.
By cutting down on data sent, you can improve the app/mobile user experience. For app developers who are concerned about their app's battery and bandwidth usage, this could be a vital feature.
Components of ContentDB Records
A ContentDB record is made up of the schema
, the contentKey
, and the JSON objects within each contentkey
.
What | Description | Example |
---|---|---|
schemas | "Folder" that contains records, usually grouped around a theme | Song |
contentKey | The record you want to tie metadata to | 1234 |
JSON Object Key | Metadata nestled in the contentkey record. Tied with the Value | {"title": "Somebody To Love"} |
JSON Object Value | Metadata nestled in the contentkey record. Tied with the Key | {"title": "Somebody To Love"} |
There can be multiple JSON objects tied to the same
contentkey
record
{
"title": "Somebody To Love",
"artist": "Queen",
"genres": ["classic rock", "electric guitar"]`
}
Naming Rules
Schema and ContentKey rules
What | Rule |
---|---|
Case-Insensitive | Names treated as lower case |
Letters, numbers, dashes, underscores | Allowed |
Periods, slashes, other punctuation | Not Allowed |
Whitespaces | Allowed, but you will need to URLEncode the schema name in the API Request, such as http://e-<network-id>.adzerk.net/cdb/<network-id>/custom/track%20information/410 |
JSON Object Rules
What | Rule |
---|---|
Case-Sensitive | Names respect cases |
Whitespace | Allowed |
Double Colons :: | Not allowed, reserved for macros |
Double Curly Brackets {{}} | Not allowed, reserved for macros |
Creating Schemas & ContentKeys
You can create records in ContentDB using our Create ContentDB Record API.
You must create ContentDB records before calling schemas and content keys in your request. At this time there is no UI functionality for adding or modifying ContentDB records.
Currently, you cannot retrieve a list of all ContentDB entries in your network.
Passing ContentKey in Decision API Request
When making a Decision API Request, you'll want to use the contentKeys
field in the Placements object.
The format is "contentKeys": {"schema": "contentKey"}
. For example:
"placements": [{
"divName": "frontpage",
"networkId": 1234,
"siteId": 12345,
"adTypes": [5],
"contentKeys": {"song": 1234, "station": 2345}
}]
Notice how in this example you are sending two
contentkeys
. This is allowed as long as those keys are tied to different schemas. You cannot send multiplecontentkeys
tied to the same schema.
Passing ContentKey in ados.js Requests
Add the .setContentKeys()
method to the ados_add_placement();
function in your JavaScript ad request to pass in your schemas(s) and content key(s).
The JSON object associated with the content key will be looked up in ContentDB and then be available for use by custom targeting and creatives (via a macro).
The format is .setContentKeys({"schema": "contentKey"})
.
For example: ados_add_placement(1234, 12345, "atf", 5).setContentKeys({"artist": 2993, "track": 3463477});
Enabling Custom Targeting with ContentDB
To target data stored in ContentDB, use a Zerkel value with Custom Targeting based on the$content.custom
Reserved Key.
For example, let's take these contentkey
records under the song
schema for our Prometheus example:
Schema: Song
Song 1234:
{
"title": "Somebody To Love",
"artist": "Queen",
"genres": ["classic rock", "electric guitar"]`
}
Song 4567:
{
"title": "Why Can't This Be Love",
"artist": "Van Halen",
"genres": ["classic rock", "electric guitar"]`
}
Prometheus will then want to set up Custom Targeting using the Zerkel template of $content.custom.[Schema].[The JSON object Key of the ContentKey]
.
For instance:
What | Zerkel Query | Eligible to Appear For |
---|---|---|
Fender wants to target songs that are in the "classic rock" genre so as to promote their guitars | $content.custom.song.genres contains "classic rock" | Song 1234 & Song 4567 |
20th Century Fox wants to advertise their "Bohemian Rhapsody" movie to Queen listeners | $content.custom.song.artist contains "queen" | Song 1234 |
1-800-Flowers wants to target anyone who listens to a song with the word 'love' in it | $content.custom.song.title contains "love" | Song 1234 & Song 4567 |
The benefit to Prometheus here is that all they need to do is pass the Song ID to enable this genre targeting!
You can also target only requests that have schema data via setting
$content.custom.album <> null
Enabling Dynamic Ad Copy With Macros
This functionality allows you to insert any data from a contentkey
record into the ad copy in real-time, enabling dynamic ad copy that will help with engagement rates.
You'll want to use Macros in a creative. The base macro is {{content.custom}}
, and the format is
{{content.custom.[schema name].[the JSON object key of the contentkey]
For example, using the Queen example above, a HTML creative with this macro...
"If you like {{content.custom.song.artist}}
, check out the new movie Bohemian Rhapsody!"
...would be rendered, "If you like Queen, check out the new movie Bohemian Rhapsody!", assuming the API Request includes "contentKeys": {"song": 1234}
. (In the above example, the record for Song 1234 includes Queen as the Artist).
The benefit of this is that if 20th Century Fox wanted to do the same thing for people listening to songs by Scorpion ("If you like Scorpion"), Styx, Van Halen, etc, they need only one creative - instead of setting up different ads for every artist!
Macros currently only support strings and numbers, so please refrain from using a macro tied to an array of objects.
If has a whitespace, to access the track information object in a macro, you must use bracket notation:
{{content.custom['track information']}}
Updated over 1 year ago