Skip to content

Commit

Permalink
implement taboola ad-type
Browse files Browse the repository at this point in the history
  • Loading branch information
Effie Nadiv authored and nitzanvolman committed Feb 2, 2016
1 parent 0bcc70b commit 79a58e5
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 5 deletions.
4 changes: 3 additions & 1 deletion 3p/integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,14 @@ import {twitter} from './twitter';
import {register, run} from '../src/3p';
import {parseUrl} from '../src/url';
import {assert} from '../src/asserts';
import {taboola} from '../ads/taboola';

/**
* Whether the embed type may be used with amp-embed tag.
* @const {!Object<string: boolean>}
*/
const AMP_EMBED_ALLOWED = {
/* embed type: true */
taboola: true
};

register('a9', a9);
Expand All @@ -51,6 +52,7 @@ register('adsense', adsense);
register('adtech', adtech);
register('plista', plista);
register('doubleclick', doubleclick);
register('taboola', taboola);
register('_ping_', function(win, data) {
win.document.getElementById('c').textContent = data.ping;
});
Expand Down
1 change: 1 addition & 0 deletions ads/_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const adPrefetch = {
export const adPreconnect = {
adreactor: 'https://adserver.adreactor.com',
adsense: 'https://googleads.g.doubleclick.net',
taboola: 'https://cdn.taboola.com',
doubleclick: [
'https://partner.googleadservices.com',
'https://securepubads.g.doubleclick.net',
Expand Down
74 changes: 74 additions & 0 deletions ads/taboola.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Copyright 2015 The AMP HTML Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import {loadScript, validateDataExists, validateExactlyOne} from '../src/3p';

/**
* @param {!Window} global
* @param {!Object} data
*/
export function taboola(global, data) {
// do not copy the following attributes from the 'data' object
// to _tablloa global object
const blackList = ['height', 'initialWindowHeight', 'initialWindowWidth',
'type', 'width', 'placement', 'mode'];

// ensure we have vlid publisher, placement and mode
// and exactly one page-type
validateDataExists(data, ['publisher', 'placement', 'mode']);
validateExactlyOne(data, ['article', 'video', 'photo', 'search', 'category',
'homepage', 'others']);

// setup default values for referrer and url
const params = {
referrer: data.referrer || global.context.referrer,
url: data.url || global.context.canonicalUrl
};

// copy none blacklisted attribute to the 'params' map
Object.keys(data).forEach(k => {
if (blackList.indexOf(k) === -1) {
params[k] = data[k];
}
});

// push the two object into the '_taboola' global
(global._taboola = global._taboola || []).push([{
viewId: global.context.pageViewId,
publisher: data.publisher,
placement: data.placement,
mode: data.mode,
framework: 'amp',
container: 'c'
},
params]);

// install observation on entering/leaving the view
global.context.observeIntersection(function(changes) {
changes.forEach(function(c) {
if (c.intersectionRect.height) {
global._taboola.push({
visible: true,
rects: c,
placement: data.placement
});
}
});
});

// load the taboola loader asynchronously
loadScript(global, `https://cdn.taboola.com/libtrc/${encodeURIComponent(data.publisher)}/loader.js`);
}
51 changes: 51 additions & 0 deletions ads/taboola.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!---
Copyright 2015 The AMP HTML Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

# Taboola

## Example

### Basic

```html
<amp-embed width=100 height=283
type=taboola
layout=responsive
heights="(min-width:1907px) 39%, (min-width:1200px) 46%, (min-width:780px) 64%, (min-width:480px) 98%, (min-width:460px) 167%, 196%"
data-publisher="amp-demo"
data-mode="thumbnails-a"
data-placement="Ads Example"
data-article="auto">
</amp-embed>
```

## Configuration

For semantics of configuration, please see ad network documentation.

Supported parameters:

- data-publisher
- data-placement
- data-mode
- data-article
- data-video
- data-photo
- data-home
- data-category
- data-others
- data-url
- data-referrer
14 changes: 12 additions & 2 deletions examples/ads.amp.html
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,19 @@ <h2>plista</h2>
data-widgetname="iAMP_2"
data-geo="de"
data-urlprefix=""
data-categories="politik"
>
data-categories="politik">
</amp-ad>

<h2>Taboola responsive widget</h2>
<amp-embed width=100 height=283
type=taboola
layout=responsive
heights="(min-width:1907px) 39%, (min-width:1200px) 46%, (min-width:780px) 64%, (min-width:480px) 98%, (min-width:460px) 167%, 196%"
data-publisher="amp-demo"
data-mode="thumbnails-a"
data-placement="Ads Example"
data-article="auto">
</amp-embed>

</body>
</html>
12 changes: 12 additions & 0 deletions examples/responsive.amp.html
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,18 @@ <h1 itemprop="headline">Lorem Ipsum</h1>
felis aliquet maximus. Class aptent taciti sociosqu ad litora
torquent per conubia nostra, per inceptos himenaeos.
</p>

<amp-embed width=100 height=283
type=taboola
layout=responsive
heights="(min-width:1907px) 39%, (min-width:1200px) 46%, (min-width:780px) 64%, (min-width:480px) 98%, (min-width:460px) 167%, 196%"
data-publisher="amp-demo"
data-mode="thumbnails-a"
data-placement="Responsive example"
data-article="auto">
</amp-embed>


</div>
</div>
</article>
Expand Down
35 changes: 35 additions & 0 deletions src/3p.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,41 @@ export function checkData(data, allowedFields) {
}
}

/**
* Throws an exception if data does not contains a mandatory field.
* @param {!Object} data
* @param {!Array<string>} mandatoryFields
*/
export function validateDataExists(data, mandatoryFields) {
for (let i = 0; i < mandatoryFields.length; i++) {
const field = mandatoryFields[i];
assert(data[field],
'Missing attribute for %s: %s.', data.type, field);
}
}

/**
* Throws an exception if data does not contains exactly one field
* mentioned in the alternativeField array.
* @param {!Object} data
* @param {!Array<string>} alternativeFields
*/
export function validateExactlyOne(data, alternativeFields) {
let countFileds = 0;

for (let i = 0; i < alternativeFields.length; i++) {
const field = alternativeFields[i];
if (data[field]) {
countFileds += 1;
}
}

assert(countFileds === 1,
'%s must contain exactly one of attributes: %s.',
data.type,
alternativeFields.join(', '));
}

/**
* Throws an exception if data contains a field not supported
* by this embed type.
Expand Down
62 changes: 60 additions & 2 deletions test/functional/test-3p.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* limitations under the License.
*/

import {validateSrcPrefix, validateSrcContains, checkData, validateData}
from '../../src/3p';
import {validateSrcPrefix, validateSrcContains, checkData, validateData,
validateDataExists, validateExactlyOne} from '../../src/3p';
import * as sinon from 'sinon';

describe('3p', () => {
Expand Down Expand Up @@ -76,6 +76,40 @@ describe('3p', () => {
clock.tick(1);
});

it('should accept supplied data', () => {
validateDataExists({
width: '',
height: false,
initialWindowWidth: 1,
initialWindowHeight: 2,
type: "taboola",
referrer: true,
canonicalUrl: true,
pageViewId: true,
location: true,
mode: true,
}, []);
clock.tick(1);

validateDataExists({
width: "",
type: "taboola",
foo: true,
bar: true,
}, ['foo', 'bar']);
clock.tick(1);
});

it('should accept supplied data', () => {
validateExactlyOne({
width: "",
type: "taboola",
foo: true,
bar: true,
}, ['foo', 'day', 'night']);
clock.tick(1);
});

it('should complain about unexpected args', () => {
checkData({
type: 'TEST',
Expand All @@ -96,5 +130,29 @@ describe('3p', () => {
}, ['not-whitelisted', 'foo']);
}).to.throw(/Unknown attribute for TEST: not-whitelisted2./);
});

it('should complain about missing args', () => {

expect(() => {
validateDataExists({
width: "",
type: "xxxxxx",
foo: true,
bar: true,
}, ['foo', 'bar', 'persika']);
}).to.throw(/Missing attribute for xxxxxx: persika./);

expect(() => {
validateExactlyOne({
width: "",
type: "xxxxxx",
foo: true,
bar: true,
}, ['red', 'green', 'blue']);
}).to.throw(
/xxxxxx must contain exactly one of attributes: red, green, blue./);
});


});

0 comments on commit 79a58e5

Please sign in to comment.