Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module to pass User Ids to DFP #4140

Merged
merged 20 commits into from
Sep 9, 2019
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions modules/userIdTargeting.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {config} from '../src/config';
import {getGlobal} from '../src/prebidGlobal';
import { isStr, isPlainObject, isBoolean, isFn, hasOwn, logInfo } from '../src/utils';

const MODULE_NAME = 'userIdTargeting';
const GAM = 'GAM';
const GAM_KEYS_CONFIG = 'GAM_KEYS';

export function userIdTargeting(userIds, config) {
if (!isPlainObject(config)) {
logInfo(MODULE_NAME + ': Invalid config found, not sharing userIds externally.');
return;
}

const PUB_GAM_KEYS = isPlainObject(config[GAM_KEYS_CONFIG]) ? config[GAM_KEYS_CONFIG] : {};
let SHARE_WITH_GAM = isBoolean(config[GAM]) ? config[GAM] : false;
let GAM_API;

if (!SHARE_WITH_GAM) {
logInfo(MODULE_NAME + ': Not enabled for ' + GAM);
}

if (window.googletag && isFn(window.googletag.pubads) && hasOwn(window.googletag.pubads(), 'setTargeting') && isFn(window.googletag.pubads().setTargeting)) {
GAM_API = window.googletag.pubads().setTargeting;
} else {
SHARE_WITH_GAM = false;
logInfo(MODULE_NAME + ': Could not find googletag.pubads().setTargeting API. Not adding User Ids in targeting.')
return;
}

Object.keys(userIds).forEach(function(key) {
if (userIds[key]) {
// PUB_GAM_KEYS: { "tdid": '' } means the publisher does not want to send the tdid to GAM
if (SHARE_WITH_GAM && PUB_GAM_KEYS[key] !== '') {
let uidStr;
if (isStr(userIds[key])) {
uidStr = userIds[key];
} else if (isPlainObject(userIds[key])) {
uidStr = JSON.stringify(userIds[key])
} else {
logInfo(MODULE_NAME + ': ' + key + ' User ID is not an object or a string.');
return;
}
GAM_API(
(hasOwn(PUB_GAM_KEYS, key) ? PUB_GAM_KEYS[key] : key),
[ uidStr ]
);
}
}
});
}

export function init(config) {
$$PREBID_GLOBAL$$.onEvent('auctionEnd', function() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pm-harshad-mane Can you use events.on api here instead of $$PREBID_GLOBAL$$. Sample use: https://github.com/prebid/Prebid.js/blob/master/modules/userId/index.js#L252

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, @jaiminpanchal27 , I have pushed the suggested change

userIdTargeting((getGlobal()).getUserIds(), config.getConfig(MODULE_NAME));
})
}

init(config)
37 changes: 37 additions & 0 deletions modules/userIdTargeting.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## userIdTargeting Module
- This module works with userId module.
- This module is used to pass userIds to GAM in targeting so that user ids can be used to pass in Google Exchange Bidding or can be used for targeting in GAM.

## Sample config
```
pbjs.setConfig({

// your existing userIds config

usersync: {
userIds: [{...}, ...]
},

// new userIdTargeting config

userIdTargeting: {
"GAM": true,
"GAM_KEYS": {
"tdid": "TTD_ID" // send tdid as TTD_ID
}
}
});
```

## Config options
- GAM: is required to be set to true if a publisher wants to send UserIds as targeting in GAM call. This module uses ``` googletag.pubads().setTargeting('key-name', ['value']) ``` API to set GAM targeting.
- GAM_KEYS: is an optional config object to be used with ``` "GAM": true ```. If not passed then all UserIds are passed with respective key-name used in UserIds object.
If a publisher wants to pass ```UserId.tdid``` as TTD_ID in targeting then set ``` GAM_KEYS: { "tdid": "TTD_ID" }```
If a publisher does not wants to pass ```UserId.tdid``` but wants to pass other Ids in UserId tthen set ``` GAM_KEYS: { "tdid": "" }```

## Including this module in Prebid
``` $ gulp build --modules=userId,userIdTargeting,pubmaticBidAdapter ```

## Notes
- We can add support for other external systems like GAM in future
- We have not added support for A9/APSTag as it is called in parallel with Prebid. This module executes when ```pbjs.requestBids``` is called, in practice, call to A9 is expected to execute in paralle to Prebid thus we have not covered A9 here. For sending Uids in A9, one will need to set those Ids in params key in the object passed to ```apstag.init```, ```pbjs.getUserIds``` can be used for the same.
53 changes: 53 additions & 0 deletions test/spec/modules/shareUserIds_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import {userIdTargeting} from '../../../modules/userIdTargeting';
import { expect } from 'chai';

describe('#userIdTargeting', function() {
let userIds;
let config;

beforeEach(function() {
userIds = {
tdid: 'my-tdid'
};
config = {
'GAM': true,
'GAM_KEYS': {
'tdid': 'TD_ID'
}
};
});

it('Do nothing if config is invaild', function() {
let pubads = window.googletag.pubads();
pubads.clearTargeting();
pubads.setTargeting('test', ['TEST']);
userIdTargeting(userIds, JSON.stringify(config));
expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']});
});

it('all UserIds are passed as is with GAM: true', function() {
let pubads = window.googletag.pubads();
pubads.clearTargeting();
pubads.setTargeting('test', ['TEST']);
delete config.GAM_KEYS;
userIdTargeting(userIds, config);
expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], tdid: ['my-tdid']});
})

it('Publisher prefered key-names are used', function() {
let pubads = window.googletag.pubads();
pubads.clearTargeting();
pubads.setTargeting('test', ['TEST']);
userIdTargeting(userIds, config);
expect(pubads.getTargeting()).to.deep.equal({test: ['TEST'], 'TD_ID': ['my-tdid']});
});

it('Publisher does not want to pass an id', function() {
let pubads = window.googletag.pubads();
pubads.clearTargeting();
pubads.setTargeting('test', ['TEST']);
config.GAM_KEYS.tdid = '';
userIdTargeting(userIds, config);
expect(pubads.getTargeting()).to.deep.equal({test: ['TEST']});
});
});
13 changes: 13 additions & 0 deletions test/spec/unit/pbjs_api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ var createSlotArrayScenario2 = function createSlotArrayScenario2() {

window.googletag = {
_slots: [],
_targeting: {},
pubads: function () {
var self = this;
return {
Expand All @@ -117,6 +118,18 @@ window.googletag = {

setSlots: function (slots) {
self._slots = slots;
},

setTargeting: function(key, arrayOfValues) {
self._targeting[key] = arrayOfValues;
},

getTargeting: function() {
return self._targeting;
},

clearTargeting: function() {
self._targeting = {};
}
};
}
Expand Down