Simplify your DFP business logic.
$ bower i harmony
$ npm i harmonyjs
Harmony is provided as both a CommonJS module via npm install harmonyjs
and as a JS global variable via bower install harmony
.
Harmony is a DFP supplement meant for large-scale enterprise advertising systems. There are methods to help you quickly create new ad slots, adjust targeting on the fly, and attach side-effects.
The original purpose behind the creation of Harmony was to provide a lightning-fast JS API that could ingest a block of JSON ad configuration to set up ads for a page. Beyond that, however, there are many utility methods that simplify DFP ad code and give you powerful tools to build dynamic page content around ad performance.
There is also built-in ad logging and metrics provided via the Lumberjack library.
Full docs are available here, but let's go over some of the best parts of Harmony. If you don't see support for something you are trying to do, chances are it's in there somewhere! Just give the docs a quick scan.
There are two ways to load Harmony:
<script src="https://github.com/cobbdb/harmony/raw/master/path/to/harmony.js"></script>
<script>
console.log(harmony.version);
</script>
var harmony = require('harmonyjs');
global.console.log(harmony.version);
Have your backend generate configurations based on admin settings and keep the components completely agnostic.
var myconf = {% generate_ad_slots %};
harmony.load.slots(myconf);
Easily attach behaviors based on the ad call, rather than side-effects such as container visibility or size. Harmony lets you code deliberately!
harmony.slot('MY01').on('slotRenderEnded', function (event) {
if (!event.isEmpty) {
// Some business logic here.
}
});
Harmony exposes individual slot configuration for pain-free access.
var slot = harmony.slot('MY01'),
possibleSizes = slot.sizes,
slotId = slot.id,
slotAdunit = slot.adunit;
You can even directly call DFP slot methods.
var slot = harmony.slot('MY01'),
targeting = slot.gpt.getTargetingMap();
slot.gpt.setTargeting('some', 'new targeting!');
Harmony features a robust eventing system that will avoid race conditions on even the most complex websites.
// System-level events.
harmony.trigger('myevent', somedata);
// Slot-level events.
harmony.slot('MY01').trigger('anotherevent');
harmony.on('myevent', function () {});
harmony.one('myevent', function () {});
harmony.slot('MY01').on('myevent', function () {});
harmony.slot('MY01').one('myevent', function () {});
GPT's slotRenderEnded
and impressionViewable
events are handled
automatically for you on each slot.
harmony.slot('MY01').on('slotRenderEnded', function (event) {});
harmony.slot('MY01').on('impressionViewable', function (event) {});
Callbacks are eager by default, meaning that they will trigger on binding if the event has already been triggered. If you do not want this behavior you can specify the callback be lazy instead.
harmony.slot('MY01').on('myLazyEvent', function () {}, true);
harmony.one('myLazyEvent', function () {}, true);
harmony.off('myevent');
Logging is off by default for performance, but can be easily enabled.
// Enable logging before page refresh.
localStorage.lumberjack = 'on';
// Enable logging without page refresh.
harmony.log.enable();
Logging lets you see what happened and when, so you can focus less on debugging and more on coding.
harmony.log.readback('events', true);
See exactly how long your system takes from setup to ad render. Logging provided with Lumberjack.
harmony.log.readback('metric', true);
Here is an example of a page setup using Harmony and DFP.
<head>
<script src="https://github.com/cobbdb/harmony/raw/master/path/to/harmony.js"></script>
<script src="https://github.com/cobbdb/harmony/raw/master//www.googletagservices.com/tag/js/gpt.js"></script>
</head>
<body>
<div id="my-ad-div"></div>
<script>
harmony.defineSlot({
name: 'my-ad',
id: 'my-ad-div',
adunit: '123/ad/unit',
sizes: [
[300, 250],
[728, 90]
],
targeting: {
some: 'custom criteria'
}
});
harmony.show.slot('my-ad');
</script>
</body>
How to test and build your changes.
# Full test suite.
$ grunt test
# Test a single spec.
$ grunt test --spec=spec.name
# Full build suite minus autodocs.
$ grunt
/tasks/build-docs/readme.tpl
# Full build including autodocs, tag, and deploy.
$ grunt version:<type>:"<msg>"
# Type can be major, minor, patch.