Skip to content

Commit

Permalink
Add meta tag to variable list in story ads (ampproject#37433)
Browse files Browse the repository at this point in the history
  • Loading branch information
powerivq authored and samouri committed Feb 2, 2022
1 parent db67bfe commit c103086
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 17 deletions.
43 changes: 43 additions & 0 deletions examples/amp-story/fake-ad.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<script async custom-element="amp-video" src="https://cdn.ampproject.org/v0/amp-video-0.1.js"></script>
<script async custom-element="amp-audio" src="https://cdn.ampproject.org/v0/amp-audio-0.1.js"></script>
<script async custom-element="amp-story" src="https://cdn.ampproject.org/v0/amp-story-1.0.js"></script>
<script async custom-element="amp-analytics" src="https://cdn.ampproject.org/v0/amp-analytics-0.1.js"></script>
<script async custom-element="amp-story-auto-ads" src="https://cdn.ampproject.org/v0/amp-story-auto-ads-0.1.js"></script>
<title>My Story</title>
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
Expand All @@ -28,6 +29,48 @@
</head>

<body>
<amp-analytics>
<script type="application/json">
{
"transport": {
"beacon": false,
"xhrpost": false,
"image": true
},
"requests": {
"endpoint": "https://www.cool.example",
"base": "${endpoint}?id=${adId}&zx=${timestamp}"
},
"triggers": {
"storyAdView": {
"on": "story-ad-view",
"request": "base",
"extraUrlParams": {"amp_stads": "view", "type": "${METATAG_AD_amp-cta-type}"}
},
"storyAdSwipe": {
"on": "story-ad-swipe",
"request": "base",
"extraUrlParams": {"amp_stads": "swipe"}
},
"storyAdClick": {
"on": "story-ad-click",
"request": "base",
"extraUrlParams": {"amp_stads": "click"}
},
"storyAdExit": {
"on": "story-ad-exit",
"request": "base",
"extraUrlParams": {"amp_stads": "exit"}
},
"storyAdDestroy": {
"on": "story-ad-discard",
"request": "base",
"extraUrlParams": {"amp_stads": "discard"}
}
}
}
</script>
</amp-analytics>
<amp-story
title="Amp-story-doubleclick"
publisher="The AMP Team"
Expand Down
20 changes: 15 additions & 5 deletions extensions/amp-story-auto-ads/0.1/story-ad-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {
A4AVarNames,
START_CTA_ANIMATION_ATTR,
createCta,
getStoryAdMacroTags,
getStoryAdMetaTags,
getStoryAdMetadataFromDoc,
getStoryAdMetadataFromElement,
maybeCreateAttribution,
Expand Down Expand Up @@ -239,6 +241,7 @@ export class StoryAdPage {
}

const uiMetadata = map();
const metaTags = getStoryAdMetaTags(this.adDoc_ ?? this.adElement_);

// Template Ads.
if (!this.adDoc_) {
Expand All @@ -249,7 +252,7 @@ export class StoryAdPage {
} else {
Object.assign(
uiMetadata,
getStoryAdMetadataFromDoc(this.adDoc_),
getStoryAdMetadataFromDoc(metaTags),
// TODO(ccordry): Depricate when possible.
this.readAmpAdExit_()
);
Expand All @@ -265,14 +268,21 @@ export class StoryAdPage {
this.localizationService_
) || uiMetadata[A4AVarNames.CTA_TYPE];

// Store the cta-type as an accesible var for any further pings.
this.analytics_.then((analytics) =>
this.analytics_.then((analytics) => {
// Store the cta-type as an accesible var for any further pings.
analytics.setVar(
this.index_, // adIndex
AnalyticsVars.CTA_TYPE,
uiMetadata[A4AVarNames.CTA_TYPE]
)
);
);

// Set meta tag based variables.
for (const [key, value] of Object.entries(
getStoryAdMacroTags(metaTags)
)) {
analytics.setVar(this.index_, `STORY_AD_META_${key}`, value);
}
});

if (
(this.adChoicesIcon_ = maybeCreateAttribution(
Expand Down
32 changes: 24 additions & 8 deletions extensions/amp-story-auto-ads/0.1/story-ad-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,23 @@ const DataAttrs = {
};

/**
* Finds all meta tags starting with `amp4ads-vars-` or `amp-cta`.
* Finds all meta tags like `amp4ads-vars-` or `amp-cta`.
* @param {Document} doc
* @return {!IArrayLike}
* @return {!NodeList}
*/
export function getStoryAdMetaTags(doc) {
const selector = 'meta[name^=amp4ads-vars-],meta[name^=amp-cta-]';
return doc.querySelectorAll(selector);
return doc.querySelectorAll('meta[name]');
}

/**
* Creates object containing information extracted from the creative
* that is needed to render story ad ui e.g. cta, attribution, etc.
* @param {!Document} doc
* @param {!NodeList} metaTags
* @return {StoryAdUIMetadata}
*/
export function getStoryAdMetadataFromDoc(doc) {
const storyMetaTags = getStoryAdMetaTags(doc);
export function getStoryAdMetadataFromDoc(metaTags) {
const vars = map();
iterateCursor(storyMetaTags, (tag) => {
iterateCursor(metaTags, (tag) => {
const {content, name} = tag;
if (name.startsWith(CTA_META_PREFIX)) {
const key = name.split('amp-')[1];
Expand All @@ -93,6 +91,24 @@ export function getStoryAdMetadataFromDoc(doc) {
return vars;
}

/**
* Returns an object conntaining all meta tags that
* qualifies as a macro (name=>value)
* @param {!NodeList} metaTags
* @return {!Object}
*/
export function getStoryAdMacroTags(metaTags) {
const result = map();
iterateCursor(metaTags, (tag) => {
const {content, name} = tag;
// If the meta tag name is not alphanumerical, we would ignore it.
if (/^[a-zA-Z0-9\-_]+$/.test(name)) {
result[name] = content;
}
});
return result;
}

/**
* Gets story ad UI metadata from the <amp-ad> element.
* @param {!Element} adElement
Expand Down
30 changes: 27 additions & 3 deletions extensions/amp-story-auto-ads/0.1/test/test-story-ad-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import {ButtonTextFitter} from '../story-ad-button-text-fitter';
import {
A4AVarNames,
createCta,
getStoryAdMacroTags,
getStoryAdMetaTags,
getStoryAdMetadataFromDoc,
getStoryAdMetadataFromElement,
maybeCreateAttribution,
Expand All @@ -20,14 +22,15 @@ describes.realWin('story-ad-ui', {amp: true}, (env) => {
doc = win.document;
});

describe('getStoryAdMetadataFromDoc', () => {
describe('meta tags', () => {
it('returns metadata for amp-* values', () => {
const adDoc = doc.implementation.createHTMLDocument();
adDoc.head.innerHTML = `
<meta name="other-tag" content="random-val">
<meta name="amp-cta-type" content="SHOP">
<meta name="amp-cta-url" content="https://www.kittens.com">
`;
const result = getStoryAdMetadataFromDoc(adDoc);
const result = getStoryAdMetadataFromDoc(getStoryAdMetaTags(adDoc));
expect(result).to.eql({
'cta-type': 'SHOP',
'cta-url': 'https://www.kittens.com',
Expand All @@ -37,19 +40,40 @@ describes.realWin('story-ad-ui', {amp: true}, (env) => {
it('returns metadata for amp4ads-vars-* values', () => {
const adDoc = doc.implementation.createHTMLDocument();
adDoc.head.innerHTML = `
<meta name="other-tag" content="random-val">
<meta name="amp4ads-vars-cta-type" content="SHOP">
<meta name="amp4ads-vars-cta-url" content="https://www.kittens.com">
<meta name="amp4ads-vars-attribution-icon" content="https://www.kittens.com/img1">
<meta name="amp4ads-vars-attribution-url" content="https://www.kittens.com/moreinfo">
`;
const result = getStoryAdMetadataFromDoc(adDoc);
const result = getStoryAdMetadataFromDoc(getStoryAdMetaTags(adDoc));
expect(result).to.eql({
'cta-type': 'SHOP',
'cta-url': 'https://www.kittens.com',
'attribution-icon': 'https://www.kittens.com/img1',
'attribution-url': 'https://www.kittens.com/moreinfo',
});
});

it('getStoryAdMacroTags should return all tags', () => {
const adDoc = doc.implementation.createHTMLDocument();
adDoc.head.innerHTML = `
<meta name="other-tag" content="random-val">
<meta name="invalid-tag-name-*" content="random-val">
<meta name="amp4ads-vars-cta-type" content="SHOP">
<meta name="amp4ads-vars-cta-url" content="https://www.kittens.com">
<meta name="amp4ads-vars-attribution-icon" content="https://www.kittens.com/img1">
<meta name="amp4ads-vars-attribution-url" content="https://www.kittens.com/moreinfo">
`;
const result = getStoryAdMacroTags(getStoryAdMetaTags(adDoc));
expect(result).to.eql({
'other-tag': 'random-val',
'amp4ads-vars-cta-type': 'SHOP',
'amp4ads-vars-cta-url': 'https://www.kittens.com',
'amp4ads-vars-attribution-icon': 'https://www.kittens.com/img1',
'amp4ads-vars-attribution-url': 'https://www.kittens.com/moreinfo',
});
});
});

describe('getStoryAdMetadataFromElement', () => {
Expand Down
3 changes: 2 additions & 1 deletion src/inabox/inabox-story-ad.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {ButtonTextFitter} from '../../extensions/amp-story-auto-ads/0.1/story-ad
import {
START_CTA_ANIMATION_ATTR,
createCta,
getStoryAdMetaTags,
getStoryAdMetadataFromDoc,
maybeCreateAttribution,
validateCtaMetadata,
Expand All @@ -17,7 +18,7 @@ import {installStylesForDoc} from '../style-installer';
export function maybeRenderInaboxAsStoryAd(ampdoc) {
const {win} = ampdoc;
const doc = win.document;
const storyAdMetadata = getStoryAdMetadataFromDoc(doc);
const storyAdMetadata = getStoryAdMetadataFromDoc(getStoryAdMetaTags(doc));
if (!validateCtaMetadata(storyAdMetadata, true /* opt_inabox */)) {
return;
}
Expand Down

0 comments on commit c103086

Please sign in to comment.