# Write an OnExtraction Middlewares for Doubleclick Ad Server
This article explains the steps to implement an OnExtraction Middleware for Doubleclick Ad Server Provider.
# Doubleclick Ad Server Provider
Doubleclick Ad Server has different properties available at its schema (opens new window) and one of them is the json.targeting
property. For this example, we will add the targeting found within a script
tag inside the tenant's HTML source code.
To extract values from the original HTML of a page, we use the OnExtraction Middleware.
# OnExtraction Middleware Implementation guide
First of all, locate where the data that we want to extract from the HTML client source code is.
This example shows how a configuration for category
and tags
targeting can look like in a tenant's source code:
<script>
window.googletag = window.googletag || {cmd: []};
googletag.cmd.push(function() {
//...
googletag.pubads().setTargeting("category", ["news"] );
googletag.pubads().setTargeting("tags", ["electricity","eskom","featured","south africa"] );
//...
});
</script>
Our objective is to extract this information and send it to the Ad Server in an object that can be merged with the one defined at the inventory. So, it has to partially match with the Config object of Doubleclick (opens new window). In this case, the result object will be something like this:
{
json: {
targeting: {
category: ["news"],
tags: ["featured","schools","south africa","teachers"]
}
}
}
# Set up
Once you found the data you need to extract, the next step is to set up all that we need to create our middleware.
First, create the src/middlewares/inventory/dfpTargetingDetector/on-extraction.ts
file for the implementation, and the src/middlewares/inventory/dfpTargetingDetector/on-extraction.test.ts
file for the test.
Then, install:
- Middleware test utils package
npm i --save-dev @marfeel/middlewares-test-utils
- Middleware types package
npm i --save-dev @marfeel/middlewares-types
- and Doubleclick Adserver Provider package (unless it's already installed)
npm i @marfeel/adserver-providers-doubleclick
# Create a test
We recommend using a test-driven approach so, let's create the tests first.
Run the npm run create:fixtures
command to automatically generate the fixtures.
You can check the How to create tests for Middleware (opens new window) article to see in detail how to create a test for an onExtraction middleware.
We will need to load the fixture we have created and run our middleware with it. Then, we must verify that the result obtained from executing it is an object like the one we need.
//on-extraction.test.ts
import { loadFixture, runMiddleware } from '@marfeel/middlewares-test-utils';
import { onExtraction } from './on-extraction';
describe('Doubleclick', () => {
describe('OnExtraction', () => {
test('returns the dfp targeting', async() => {
const document = await loadFixture('news-when-learners-return-to-school-what-date-matric-exam-results-released.html');
const result = await runMiddleware(document, onExtraction);
expect(result).toEqual({
json: {
targeting: {
category: ['news'],
tags: ['featured', 'schools', 'south africa', 'teachers']
}
}
});
});
});
});
# Middleware Implementation
Once the test is ready, you need to obtain the data from the script.
For do it we can use the Middleware helper functions to mock the window object and execute the scripts that will populate the mocked object with the data we need to retrieve.
First we are going to create the mock of the object that the script uses. This object has to have everything necessary for the script to run without failure and with all the functions that are used in the script even they are not relevant for us.
We configure the function setTargeting
to be able to populate the targeting
object with the values that are sent by parameter since these are the ones that we want to collect.
const targetingObject: {
[key: string]: string;
[key: string]: Array<string>;
} = {};
const googletag = {
targeting: targetingObject,
cmd: {
push: function (f: () => void) {
f();
}
},
setTargeting: function(key: string, value: Array<string>) {
this.targeting[key] = value;
return this;
}
//...
};
We call the installMock
method passing the object that we just created and the window property we want to retrive. And then we use the execute method to run the target script. As a parameter, we will add a string that partially matches the content of the script.
Once the script has run, it will have modified window.targeting
with the values that we need, so they will be available at the mock
object.
const mock: any = helpers.installMock(googletag, 'googletag');
helpers.execute('googletag.pubads().setTargeting');
const targeting = mock.targeting;
After obtaining the data from the script, you need the onExtraction hook to return the result as an object partially matching the Doubleclick Config
type.
The final result will look similar to this example:
//on-extraction.ts
import { onExtractionFunction } from '@marfeel/middlewares-types';
import { Config } from '@marfeel/adserver-providers-doubleclick';
export const onExtraction: onExtractionFunction<Partial<Config>> = async ({ document, helpers }): Promise<Partial<Config>> => {
const targetingObject: {
[key: string]: Array<string>;
} = {};
const googletag = {
targeting: targetingObject,
cmd: {
push: function (f: () => void) {
f();
}
},
setTargeting: function(key: string, value: Array<string>) {
this.targeting[key] = value;
return this;
}
};
const mock: any = helpers.installMock(googletag, 'googletag');
helpers.execute('googletag.pubads().setTargeting');
return {
json: {
targeting: mock.targeting
}
};
};
Now, it's time to run npm test
and validate the tests are passing.
To test the implementation in production pages, first run npm run build
and then npm run middleware dfpTargetingDetector https://example.com/article-containing-dfp-targeting/
.
# Connect the pieces
- Add the
invokeMiddleware
flag to thefeatures.json
and set it totrue
.
//features.json
{
"features": {
"invokeMiddleware": true
}
}
- Add the middleware to the Ad Server on
inventory.json
. It should be always at the top level of the Ad Server Config and its name has to be the same name you used to create the middleware folder.
//inventory.json
{
"placements": {
"bottom_details_1": {
"adServer": "dfp"
}
},
"adServers": {
"dfp": {
"type" : "doubleclick",
"slot" : "/123456/test.com",
"middleware": "dfpTargetingDetector"
}
}
}
Now you can test the middleware with a tenant in your local environment or with a Preview Branch and check if the DFP calls contain the desired targeting.
WARNING
If you are replacing a Metadata Provider for an OnExtraction Middleware, remember to remove all the old Metadata Provider files and their references.
Here you can find a a real OnExtraction Middleware example (opens new window)