Skip to content

Commit

Permalink
GDPR: Ability to enable/disable personalized ads. (#98)
Browse files Browse the repository at this point in the history
* Ability to enable/disable personalized ads.

 - manager api, new component prop.
 - unittests and documentation.

* fix method name
  • Loading branch information
jaanauati authored Jan 3, 2019
1 parent 02ea1b7 commit 718390c
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 3 deletions.
4 changes: 3 additions & 1 deletion Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ DFPManager.load();
| ------------------ | ------------- | ----------- | ------- |
| autoLoad | boolean (default true) | ``` { false } ``` | Tell to the provider if it should load the ads when the slots are mounted. |
| dfpNetworkId | string | ``` "1122" ``` | DFP Account id. |
| singleRequest | boolean (default true) | ```<DFPSlotsProvider singleRequest=false> ... </DFPSlotsProvider>``` | Enables or disables the gpt's singleRequest feature. |
| personalizedAds | boolean (default true) | ```<DFPSlotsProvider personalizedAds={false}> ... </DFPSlotsProvider>``` | Configure whether your page should receive personalized ads or not (see https://support.google.com/admanager/answer/7678538?hl=en). |
| singleRequest | boolean (default true) | ```<DFPSlotsProvider singleRequest={false}> ... </DFPSlotsProvider>``` | Enables or disables the gpt's singleRequest feature. |
| adUnit | string | ``` "homepage" ``` | The adunit you want to target the boxes (children / contained boxes). |
| sizeMapping | array of objects. | ```{ [ {viewport: [1024, 768], sizes:[[728, 90], [300, 250]]}, {viewport: [900, 768], sizes:[[300, 250]] }] } ``` | Set the size mappings to be applied to the nested ad slots. |
| adSenseAttributes | object | ``` { "site_url": "my.site.com", ... } ``` | Object with adSense attributes that will be applied globaly (see: https://developers.google.com/doubleclick-gpt/adsense_attributes). |
Expand Down Expand Up @@ -130,6 +131,7 @@ DFPManager.load();
| load | ```fcn([slotId]) ```| ```DFPManager.load(); ``` | Fetches the gpt api (by calling init()) and renders the ad slots in the page. You can specify an individual slot. |
| refresh | ``` fcn() ``` | ```DFPManager.refresh(); ``` | Refreshes the ad slots available in the page. This method will call load() if it wasn't already called. Use the method ```<AdSlot shouldRefresh={function(){}} ...>``` to get control over the slots to be refreshed. |
| configureSingleRequest | ```fcn(boolean)``` | ```DFPManager.configureSingleRequest( false )``` | Controls the strategy to use for the network requests. This method accepts a boolean that tells wether to enable or disable the singleRequest mode. |
| configurePersonalizedAds | ```fcn(boolean)``` | ```DFPManager.configurePersonalizedAds( false )``` | Configure the strategy to serve ads. true: serve personalized ads, false: configure dfp to not serve personalized ads (see https://support.google.com/admanager/answer/7678538?hl=en). |
| singleRequestEnabled | ```fcn() => bool``` | ``` DFPManager.singleRequestEnabled(); ``` | Returns true when the singleRequest mode is enabled, false otherwise. |
| setAdSenseAttributes | ``` fcn(object)``` | ``` DFPManager.setAdSenseAttributes({ "page_url": "www.site.com", "adsense_link_color": "#000000"}); ``` | Use this method to set AdSense attributes. |
| setAdSenseAttribute | ``` fcn(key, value)``` | ``` DFPManager.setAdSenseAttributes("page_url", "www.site.com"); ``` | Use this method to set AdSense attributes. |
Expand Down
3 changes: 3 additions & 0 deletions js/dfpslotsprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default class DFPSlotsProvider extends React.Component {
]).isRequired,
autoLoad: PropTypes.bool,
dfpNetworkId: PropTypes.string.isRequired,
personalizedAds: PropTypes.bool,
singleRequest: PropTypes.bool,
adUnit: PropTypes.string,
sizeMapping: PropTypes.arrayOf(PropTypes.object),
Expand All @@ -32,6 +33,7 @@ export default class DFPSlotsProvider extends React.Component {

static defaultProps = {
autoLoad: true,
personalizedAds: true,
singleRequest: true,
collapseEmptyDivs: null,
};
Expand All @@ -54,6 +56,7 @@ export default class DFPSlotsProvider extends React.Component {
}

componentDidMount() {
DFPManager.configurePersonalizedAds(this.props.personalizedAds);
DFPManager.configureSingleRequest(this.props.singleRequest);
DFPManager.setAdSenseAttributes(this.props.adSenseAttributes);
DFPManager.setCollapseEmptyDivs(this.props.collapseEmptyDivs);
Expand Down
18 changes: 17 additions & 1 deletion js/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ let loadInProgress = false;
let loadPromise = null;
let googleGPTScriptLoadPromise = null;
let singleRequestEnabled = true;
let servePersonalizedAds = true;
const registeredSlots = {};
let managerAlreadyInitialized = false;
const globalTargetingArguments = {};
Expand All @@ -25,6 +26,14 @@ const DFPManager = Object.assign(new EventEmitter().setMaxListeners(0), {
return globalAdSenseAttributes[key];
},

configurePersonalizedAds(value) {
servePersonalizedAds = value;
},

personalizedAdsEnabled() {
return servePersonalizedAds;
},

setAdSenseAttribute(key, value) {
this.setAdSenseAttributes({ [key]: value });
},
Expand Down Expand Up @@ -102,6 +111,9 @@ const DFPManager = Object.assign(new EventEmitter().setMaxListeners(0), {
const slotId = event.slot.getSlotElementId();
this.emit('impressionViewable', { slotId, event });
});
pubadsService.setRequestNonPersonalizedAds(
this.personalizedAdsEnabled() ? 0 : 1,
);
const targetingArguments = this.getTargetingArguments();
// set global targetting arguments
Object.keys(targetingArguments).forEach((varName) => {
Expand Down Expand Up @@ -242,7 +254,11 @@ const DFPManager = Object.assign(new EventEmitter().setMaxListeners(0), {
this.getGoogletag().then((googletag) => {
const slotsToRefresh = this.getRefreshableSlots();
googletag.cmd.push(() => {
googletag.pubads().refresh(
const pubadsService = googletag.pubads();
pubadsService.setRequestNonPersonalizedAds(
this.personalizedAdsEnabled() ? 0 : 1,
);
pubadsService.refresh(
Object.keys(slotsToRefresh).map(slotId => slotsToRefresh[slotId].gptSlot),
);
});
Expand Down
4 changes: 4 additions & 0 deletions lib/dfpslotsprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ function (_React$Component) {
}, {
key: "componentDidMount",
value: function componentDidMount() {
_manager.default.configurePersonalizedAds(this.props.personalizedAds);

_manager.default.configureSingleRequest(this.props.singleRequest);

_manager.default.setAdSenseAttributes(this.props.adSenseAttributes);
Expand Down Expand Up @@ -115,6 +117,7 @@ _defineProperty(DFPSlotsProvider, "propTypes", {
children: _propTypes.default.oneOfType([_propTypes.default.element, _propTypes.default.array]).isRequired,
autoLoad: _propTypes.default.bool,
dfpNetworkId: _propTypes.default.string.isRequired,
personalizedAds: _propTypes.default.bool,
singleRequest: _propTypes.default.bool,
adUnit: _propTypes.default.string,
sizeMapping: _propTypes.default.arrayOf(_propTypes.default.object),
Expand All @@ -134,6 +137,7 @@ _defineProperty(DFPSlotsProvider, "childContextTypes", {

_defineProperty(DFPSlotsProvider, "defaultProps", {
autoLoad: true,
personalizedAds: true,
singleRequest: true,
collapseEmptyDivs: null
});
12 changes: 11 additions & 1 deletion lib/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var loadInProgress = false;
var loadPromise = null;
var googleGPTScriptLoadPromise = null;
var singleRequestEnabled = true;
var servePersonalizedAds = true;
var registeredSlots = {};
var managerAlreadyInitialized = false;
var globalTargetingArguments = {};
Expand All @@ -34,6 +35,12 @@ var DFPManager = Object.assign(new _events.EventEmitter().setMaxListeners(0), {
getAdSenseAttribute: function getAdSenseAttribute(key) {
return globalAdSenseAttributes[key];
},
configurePersonalizedAds: function configurePersonalizedAds(value) {
servePersonalizedAds = value;
},
personalizedAdsEnabled: function personalizedAdsEnabled() {
return servePersonalizedAds;
},
setAdSenseAttribute: function setAdSenseAttribute(key, value) {
this.setAdSenseAttributes(_defineProperty({}, key, value));
},
Expand Down Expand Up @@ -115,6 +122,7 @@ var DFPManager = Object.assign(new _events.EventEmitter().setMaxListeners(0), {
event: event
});
});
pubadsService.setRequestNonPersonalizedAds(_this.personalizedAdsEnabled() ? 0 : 1);

var targetingArguments = _this.getTargetingArguments(); // set global targetting arguments

Expand Down Expand Up @@ -267,7 +275,9 @@ var DFPManager = Object.assign(new _events.EventEmitter().setMaxListeners(0), {
var slotsToRefresh = _this4.getRefreshableSlots();

googletag.cmd.push(function () {
googletag.pubads().refresh(Object.keys(slotsToRefresh).map(function (slotId) {
var pubadsService = googletag.pubads();
pubadsService.setRequestNonPersonalizedAds(_this4.personalizedAdsEnabled() ? 0 : 1);
pubadsService.refresh(Object.keys(slotsToRefresh).map(function (slotId) {
return slotsToRefresh[slotId].gptSlot;
}));
});
Expand Down
41 changes: 41 additions & 0 deletions spec/test-dfpslotsprovider.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,47 @@ import sinon from 'sinon';
import { DFPSlotsProvider, AdSlot, DFPManager } from '../lib';

describe('DFPSlotsProvider', () => {
describe('GDPR', () => {
it('Fetches personalized ads by default', () => {
const otherProps = {
dfpNetworkId: '1000',
adUnit: 'foo/bar/baz',
};
TestUtils.renderIntoDocument(
<DFPSlotsProvider {...otherProps}>
<AdSlot slotId={'testElement'} />
</DFPSlotsProvider>,
);
expect(DFPManager.personalizedAdsEnabled()).to.equal(true);
});

it('Can disable personalized ads', () => {
const otherProps = {
dfpNetworkId: '1000',
adUnit: 'foo/bar/baz',
};
TestUtils.renderIntoDocument(
<DFPSlotsProvider personalizedAds={false} {...otherProps}>
<AdSlot slotId={'testElement'} />
</DFPSlotsProvider>,
);
expect(DFPManager.personalizedAdsEnabled()).to.equal(false);
});

it('Can enable personalized ads', () => {
const otherProps = {
dfpNetworkId: '1000',
adUnit: 'foo/bar/baz',
};
TestUtils.renderIntoDocument(
<DFPSlotsProvider personalizedAds {...otherProps}>
<AdSlot slotId={'testElement'} />
</DFPSlotsProvider>,
);
expect(DFPManager.personalizedAdsEnabled()).to.equal(true);
});
});

describe('Component markup', () => {
let component;
beforeEach(() => {
Expand Down
14 changes: 14 additions & 0 deletions spec/test-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ import { DFPManager } from '../lib';

describe('DFPManager', () => {

describe('GDPR', () => {
it('Fetches personalized ads by default', function registersAdSlot() {
expect(DFPManager.personalizedAdsEnabled()).equal(true);
});
it('Can disable personalized ads', function registersAdSlot() {
DFPManager.configurePersonalizedAds(false);
expect(DFPManager.personalizedAdsEnabled()).equal(false);
});
it('Can enable personalized ads', function registersAdSlot() {
DFPManager.configurePersonalizedAds(true);
expect(DFPManager.personalizedAdsEnabled()).equal(true);
});
});

describe('Single Request', () => {
it('Gets singleRequest enabled by default', function registersAdSlot() {
expect(DFPManager.singleRequestIsEnabled()).equal(true);
Expand Down

0 comments on commit 718390c

Please sign in to comment.