diff --git a/Readme.md b/Readme.md index 25e7548..5cad82d 100644 --- a/Readme.md +++ b/Readme.md @@ -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) | ``` ... ``` | Enables or disables the gpt's singleRequest feature. | +| personalizedAds | boolean (default true) | ``` ... ``` | Configure whether your page should receive personalized ads or not (see https://support.google.com/admanager/answer/7678538?hl=en). | +| singleRequest | boolean (default true) | ``` ... ``` | 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). | @@ -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 `````` 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. | diff --git a/js/dfpslotsprovider.js b/js/dfpslotsprovider.js index d68a9bc..ad819da 100644 --- a/js/dfpslotsprovider.js +++ b/js/dfpslotsprovider.js @@ -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), @@ -32,6 +33,7 @@ export default class DFPSlotsProvider extends React.Component { static defaultProps = { autoLoad: true, + personalizedAds: true, singleRequest: true, collapseEmptyDivs: null, }; @@ -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); diff --git a/js/manager.js b/js/manager.js index 9fde2ba..0e174fe 100644 --- a/js/manager.js +++ b/js/manager.js @@ -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 = {}; @@ -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 }); }, @@ -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) => { @@ -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), ); }); diff --git a/lib/dfpslotsprovider.js b/lib/dfpslotsprovider.js index b3cf024..4dda3ad 100644 --- a/lib/dfpslotsprovider.js +++ b/lib/dfpslotsprovider.js @@ -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); @@ -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), @@ -134,6 +137,7 @@ _defineProperty(DFPSlotsProvider, "childContextTypes", { _defineProperty(DFPSlotsProvider, "defaultProps", { autoLoad: true, + personalizedAds: true, singleRequest: true, collapseEmptyDivs: null }); \ No newline at end of file diff --git a/lib/manager.js b/lib/manager.js index 647678d..a5da9d5 100644 --- a/lib/manager.js +++ b/lib/manager.js @@ -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 = {}; @@ -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)); }, @@ -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 @@ -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; })); }); diff --git a/spec/test-dfpslotsprovider.js b/spec/test-dfpslotsprovider.js index ab23729..31d485c 100644 --- a/spec/test-dfpslotsprovider.js +++ b/spec/test-dfpslotsprovider.js @@ -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( + + + , + ); + expect(DFPManager.personalizedAdsEnabled()).to.equal(true); + }); + + it('Can disable personalized ads', () => { + const otherProps = { + dfpNetworkId: '1000', + adUnit: 'foo/bar/baz', + }; + TestUtils.renderIntoDocument( + + + , + ); + expect(DFPManager.personalizedAdsEnabled()).to.equal(false); + }); + + it('Can enable personalized ads', () => { + const otherProps = { + dfpNetworkId: '1000', + adUnit: 'foo/bar/baz', + }; + TestUtils.renderIntoDocument( + + + , + ); + expect(DFPManager.personalizedAdsEnabled()).to.equal(true); + }); + }); + describe('Component markup', () => { let component; beforeEach(() => { diff --git a/spec/test-manager.js b/spec/test-manager.js index c30b221..f62f8da 100644 --- a/spec/test-manager.js +++ b/spec/test-manager.js @@ -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);