Skip to content

Commit

Permalink
Initial smatr-ads-net (#27382)
Browse files Browse the repository at this point in the history
* Initial smatr-ads-net

* Initial smatr-ads-net

* Initial smatr-ads-net, fixes

* Initial smatr-ads-net, fixes
  • Loading branch information
approslab committed Mar 26, 2020
1 parent 2af7009 commit 72e2b39
Show file tree
Hide file tree
Showing 6 changed files with 313 additions and 0 deletions.
1 change: 1 addition & 0 deletions build-system/test-configs/dep-check-config.js
Expand Up @@ -183,6 +183,7 @@ exports.rules = [
// a4a ads depend on a4a.
'extensions/amp-ad-network-fake-impl/0.1/amp-ad-network-fake-impl.js->extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-adzerk-impl/0.1/amp-ad-network-adzerk-impl.js->extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-smartads-impl/0.1/amp-ad-network-smartads-impl.js->extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-doubleclick-impl/0.1/sra-utils.js->extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-adsense-impl/0.1/amp-ad-network-adsense-impl.js->extensions/amp-a4a/0.1/amp-a4a.js',
'extensions/amp-ad-network-doubleclick-impl/0.1/amp-ad-network-doubleclick-impl.js->extensions/amp-a4a/0.1/amp-a4a.js',
Expand Down
@@ -0,0 +1,59 @@
/**
* Copyright 2020 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 {AmpA4A} from '../../amp-a4a/0.1/amp-a4a';
import {startsWith} from '../../../src/string';

/**
* Base URL
*
* @type {string}
* @private
*/
const BASE_URL_ = 'https://smart-ads.biz/_amp';

/**
* A4A base URL
*
* @type {string}
* @private
*/
const BASE_A4A_URL_ = 'https://smart-ads.biz/_a4a';

export class AmpAdNetworkSmartAdsImpl extends AmpA4A {
/** @override */
getAdUrl(unusedConsentState, opt_rtcResponsesPromise) {
return this.element.getAttribute('src').replace(BASE_URL_, BASE_A4A_URL_);
}

/** @override */
getSigningServiceNames() {
return ['cloudflare'];
}

/** @override */
isValidElement() {
const src = this.element.getAttribute('src') || '';
return (
this.isAmpAdElement() &&
(startsWith(src, BASE_URL_) || startsWith(src, BASE_A4A_URL_))
);
}
}

AMP.extension('amp-ad-network-smartads-impl', '0.1', AMP => {
AMP.registerElement('amp-ad-network-smartads-impl', AmpAdNetworkSmartAdsImpl);
});
39 changes: 39 additions & 0 deletions extensions/amp-ad-network-smartads-impl/0.1/smartads-a4a-config.js
@@ -0,0 +1,39 @@
/**
* Copyright 2020 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 {startsWith} from '../../../src/string';

/** @const @private {string} */
const SRC_PREFIX_ = 'https://smart-ads.biz/_amp';

/** @const @private {string} */
const SRC_A4A_PREFIX_ = 'https://smart-ads.biz/_a4a';

/**
* @param {!Window} win
* @param {!Element} element
* @param {boolean} useRemoteHtml
* @return {boolean}
*/
export function smartAdsIsA4AEnabled(win, element, useRemoteHtml) {
const src = element.getAttribute('src');
return (
!useRemoteHtml &&
!!src &&
!!element.getAttribute('data-use-a4a') &&
(startsWith(src, SRC_PREFIX_) || startsWith(src, SRC_A4A_PREFIX_))
);
}
@@ -0,0 +1,143 @@
/**
* Copyright 2020 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 {AmpAdNetworkSmartAdsImpl} from '../../../amp-ad-network-smartads-impl/0.1/amp-ad-network-smartads-impl';
import {
AmpAdUIHandler, // eslint-disable-line no-unused-vars
} from '../../../amp-ad/0.1/amp-ad-ui';
import {
AmpAdXOriginIframeHandler, // eslint-disable-line no-unused-vars
} from '../../../amp-ad/0.1/amp-ad-xorigin-iframe-handler';
import {createElementWithAttributes} from '../../../../src/dom';
import {smartAdsIsA4AEnabled} from '../../../amp-ad-network-smartads-impl/0.1/smartads-a4a-config';

describes.realWin('smartads-a4a-config', {amp: false}, env => {
let win, doc;
beforeEach(() => {
win = env.win;
doc = win.document;
});
it('should pass a4a config predicate', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
src: 'https://smart-ads.biz/_amp',
'data-use-a4a': 'true',
});
expect(smartAdsIsA4AEnabled(win, element)).to.be.true;
});
it('should pass a4a config predicate', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
src: 'https://smart-ads.biz/_a4a',
'data-use-a4a': 'true',
});
expect(smartAdsIsA4AEnabled(win, element)).to.be.true;
});
it('should fail a4a config predicate due to useRemoteHtml', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
src: 'https://smart-ads.biz/_a4a',
'data-use-a4a': 'true',
});
const useRemoteHtml = true;
expect(smartAdsIsA4AEnabled(win, element, useRemoteHtml)).to.be.false;
});
it('should fail a4a config predicate due to missing use-a4a', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
src: 'https://smart-ads.biz/_amp',
});
expect(smartAdsIsA4AEnabled(win, element)).to.be.false;
});
it('should fail a4a config predicate due to missing src', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
'data-use-a4a': 'true',
});
expect(smartAdsIsA4AEnabled(win, element)).to.be.false;
});
it('should fail a4a config predicate due to invalid src', () => {
const element = createElementWithAttributes(doc, 'amp-ad', {
src: 'https://evil.com?hello=world&https://smart-ads.biz',
'data-use-a4a': 'true',
});
expect(smartAdsIsA4AEnabled(win, element)).to.be.false;
});
});

describes.realWin(
'amp-ad-network-smartads-impl',
{
amp: {
extensions: ['amp-ad-network-smartads-impl'],
},
},
env => {
let win, doc;
let impl;
let implElem;
beforeEach(() => {
win = env.win;
doc = win.document;
implElem = doc.createElement('amp-ad');
implElem.setAttribute('type', 'smartads');
implElem.setAttribute('data-use-a4a', 'true');
env.sandbox
.stub(AmpAdNetworkSmartAdsImpl.prototype, 'getSigningServiceNames')
.callsFake(() => {
return ['google'];
});
impl = new AmpAdNetworkSmartAdsImpl(implElem);
});

describe('#isValidElement', () => {
it('should be valid', () => {
implElem.setAttribute(
'src',
'https://smart-ads.biz/_a4a?buid=1&is_a4a=1'
);
expect(impl.isValidElement()).to.be.true;
});
it('should be valid', () => {
implElem.setAttribute(
'src',
'https://smart-ads.biz/_amp?buid=1&is_a4a=1'
);
expect(impl.isValidElement()).to.be.true;
});
it('should NOT be valid (impl tag name)', () => {
implElem = doc.createElement('amp-ad-network-smartads-impl');
implElem.setAttribute('type', 'smartads');
impl = new AmpAdNetworkSmartAdsImpl(implElem);
expect(impl.isValidElement()).to.be.false;
});
});

describe('#getAdUrl', () => {
it('should be valid', () => {
implElem.setAttribute(
'src',
'https://smart-ads.biz/_a4a?buid=1&is_a4a=1'
);
const base = 'https://smart-ads.biz/_a4a';
expect(impl.getAdUrl().substring(0, base.length)).to.equal(base);
});
it('should be valid', () => {
implElem.setAttribute(
'src',
'https://smart-ads.biz/_amp?buid=1&is_a4a=1'
);
const base = 'https://smart-ads.biz/_a4a';
expect(impl.getAdUrl().substring(0, base.length)).to.equal(base);
});
});
}
);
10 changes: 10 additions & 0 deletions extensions/amp-ad-network-smartads-impl/OWNERS
@@ -0,0 +1,10 @@
// For an explanation of the OWNERS rules and syntax, see:
// https://github.com/ampproject/amp-github-apps/blob/master/owners/OWNERS.example

{
rules: [
{
owners: [{name: 'ampproject/wg-ads-reviewers'}, {name: 'approslab'}],
},
],
}
@@ -0,0 +1,61 @@
<!---
Copyright 2020 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.
-->

# amp-ad-network-smartads-impl

SmartAds implementation of AMP Ad tag which requests early by XHR and renders natively within the page if a valid AMP Ad is returned. Should not be directly referenced by pages and instead is dynamically loaded via the amp-ad tag. However, in order to remove an async script load of this library, publishers can include its script declaration.

<table>
<tr>
<td class="col-fourty" width="50%"><strong>Availability</strong></td>
<td>In Development</td>
</tr>
<tr>
<td class="col-fourty"><strong>Required Script</strong></td>
<td><code>&lt;script async custom-element="amp-ad" src="https://cdn.ampproject.org/v0/amp-ad-0.1.js">&lt;/script></code></td>
</tr>
</table>

## Example

```html
<amp-ad
width="300"
height="250"
type="smartads"
data-use-a4a="true"
data-buid="123"
src="https://smart-ads.biz/_a4a"
>
</amp-ad>
```

## Attributes

SmartAds impl uses the same attributes as `<amp-ad>` .

<table>
<tr>
<td width="40%"><strong>data-use-a4a</strong></td>
<td>If non-empty, SmartAds will attempt to render via the A4A
pathway (i.e., fast rendering for AMP creatives). Otherwise, it will attempt
to render via the delayed iframe path.</td>
</tr>
<tr>
<td width="40%"><strong>data-buid</strong></td>
<td>Unique block id</td>
</tr>
</table>

0 comments on commit 72e2b39

Please sign in to comment.