Skip to content

Commit

Permalink
✨ Apester amp element: added video in-unit logic (#38503)
Browse files Browse the repository at this point in the history
* added video in-unit basic logic

* renamed handleCompanionAds to handleAds

* added in-unit video

* fixed unit tests

* fixed circleci check

* fixed videoSettings checking and deleted needless functions

* fixed unit test

* deleted needless function

* added two unit tests
  • Loading branch information
golovatuy committed Oct 31, 2022
1 parent 9664ef2 commit 8570909
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 26 deletions.
34 changes: 34 additions & 0 deletions extensions/amp-apester-media/0.1/amp-apester-media.css
Expand Up @@ -70,3 +70,37 @@
transform: translateX(-50%) !important;
margin: 0 !important;
}

.i-amphtml-amp-apester-in-unit-wrap {
display: none !important;
position: absolute !important;
top: 0 !important;
bottom: 0 !important;
left: 0 !important;
right: 0 !important;
background-color: #626262 !important;
}

.i-amphtml-amp-apester-in-unit-wrap.active {
display: block !important;
}

.i-amphtml-amp-apester-progress-bar {
width: 100%;
height: 4px;
background-color: #ee9802;
}

@keyframes progress {
from {
width: 0;
}
}

.i-amphtml-amp-apester-in-unit {
display: block!important;
position: relative!important;
top: 50%!important;
transform: translateY(-50%)!important;
margin: 0!important;
}
10 changes: 7 additions & 3 deletions extensions/amp-apester-media/0.1/amp-apester-media.js
Expand Up @@ -27,7 +27,7 @@ import {Services} from '#service';
import {IntersectionObserver3pHost} from '#utils/intersection-observer-3p-host';
import {dev, user, userAssert} from '#utils/log';

import {handleCompanionAds} from './monetization';
import {handleAds} from './monetization';
import {
extractTags,
getPlatform,
Expand All @@ -42,6 +42,7 @@ import {addParamsToUrl} from '../../../src/url';
/** @const */
const TAG = 'amp-apester-media';
const AD_TAG = 'amp-ad';
const AD_IFRAME_TAG = 'amp-iframe';
/** @const {!JsonObject} */
const BOTTOM_AD_MESSAGE = {'type': 'has_bottom_ad', 'adHeight': 50};
/**
Expand Down Expand Up @@ -321,7 +322,7 @@ class AmpApesterMedia extends AMP.BaseElement {
const overflow = this.constructOverflow_();
this.element.appendChild(overflow);
this.element.appendChild(iframe);
handleCompanionAds(media, this.element);
handleAds(media, this.element);
})
.then(() => this.loadPromise(iframe))
.then(() =>
Expand All @@ -331,10 +332,13 @@ class AmpApesterMedia extends AMP.BaseElement {

const campaignData = media['campaignData'];
if (campaignData) {
const ampdoc = this.getAmpDoc();
Services.extensionsFor(
this.win
)./*OK*/ installExtensionForDoc(ampdoc, AD_IFRAME_TAG);
const bottomAdOptions = campaignData['bottomAdOptions'];
if (bottomAdOptions?.enabled) {
this.hasBottomAd_ = true;
const ampdoc = this.getAmpDoc();
Services.extensionsFor(
this.win
)./*OK*/ installExtensionForDoc(ampdoc, AD_TAG);
Expand Down
Expand Up @@ -8,7 +8,7 @@ const ALLOWED_AD_PROVIDER = 'gpt';
* @param {!JsonObject} media
* @param {!AmpElement} apesterElement
*/
export function handleCompanionBottomAd(media, apesterElement) {
export function handleBottomAd(media, apesterElement) {
const bottomAdOptions = getValueForExpr(
/**@type {!JsonObject}*/ (media),
'campaignData.bottomAdOptions'
Expand Down
15 changes: 9 additions & 6 deletions extensions/amp-apester-media/0.1/monetization/companion/video.js
Expand Up @@ -102,17 +102,20 @@ function addCompanionAvElement(
consentObj
) {
const size = getCompanionVideoAdSize(apesterElement);
const refreshInterval = 30;
const ampAvAd = createElementWithAttributes(
/** @type {!Document} */ (apesterElement.ownerDocument),
'amp-ad',
'amp-iframe',
{
'scrolling': 'no',
'id': 'amp-iframe',
'title': 'Ads',
'layout': 'responsive',
'sandbox': 'allow-scripts allow-same-origin allow-popups',
'allowfullscreen': 'false',
'frameborder': '0',
'width': size.width,
'height': size.height,
'type': 'aniview',
'data-publisherid': '5fabb425e5d4cb4bbc0ca7e4',
'data-channelid': playerOptions.aniviewChannelId,
'data-enable-refresh': `${refreshInterval}`,
'src': `https://player.avplayer.com/amp/ampiframe.html?AV_TAGID=${playerOptions.aniviewPlayerId}&AV_PUBLISHERID=5fabb425e5d4cb4bbc0ca7e4`,
}
);

Expand Down
131 changes: 131 additions & 0 deletions extensions/amp-apester-media/0.1/monetization/inUnit/video.js
@@ -0,0 +1,131 @@
import {createElementWithAttributes} from '#core/dom';
import {setStyle} from '#core/dom/style';
import {getValueForExpr} from '#core/types/object';

import {Services} from '#service';

/**
* @param {!JsonObject} media
* @param {!AmpElement} apesterElement
* @param {!JsonObject} consentObj
*/
export function handleInUnitVideo(media, apesterElement, consentObj) {
const playerOptions = getValueForExpr(
/**@type {!JsonObject}*/ (media),
'campaignData.playerOptions'
);
if (!playerOptions) {
return;
}
const videoSettings = playerOptions.find(
(options) => options.player.type === 'va'
);
if (!videoSettings) {
return;
}
const idleOptions = videoSettings.requests.find(
(request) => request.type === 'idle'
);
const {provider} = videoSettings.player;
switch (provider.type) {
case 'aniview': {
const playerOptions = provider.options || {};
if (!playerOptions.aniviewChannelId) {
return;
}
addAvElement(
playerOptions,
apesterElement,
consentObj,
idleOptions.options
);
break;
}
default:
break;
}
}

/**
* @param {!AmpElement} adWrap
* @param {!AmpElement} progressBar
* @param {!JsonObject} idleOptions
*/
function showVideoAd(adWrap, progressBar, idleOptions) {
const {skipTimer} = idleOptions;
adWrap.classList.add('active');
setStyle(progressBar, 'animation', `progress ${skipTimer}s linear 1`);
const timer = setTimeout(() => {
adWrap.classList.remove('active');
clearTimeout(timer);
}, skipTimer * 1000);
}

/**
* @param {!JsonObject} playerOptions
* @param {!AmpElement} apesterElement
* @param {!JsonObject} consentObj
* @param {!JsonObject} idleOptions
*/
function addAvElement(playerOptions, apesterElement, consentObj, idleOptions) {
const size = getCompanionVideoAdSize(apesterElement);
const ampAvAd = createElementWithAttributes(
/** @type {!Document} */ (apesterElement.ownerDocument),
'amp-iframe',
{
'scrolling': 'no',
'id': 'amp-iframe',
'title': 'Ads',
'layout': 'responsive',
'sandbox': 'allow-scripts allow-same-origin allow-popups',
'allowfullscreen': 'false',
'frameborder': '0',
'width': size.width,
'height': size.height,
'class': 'i-amphtml-amp-apester-in-unit',
'src': `https://player.avplayer.com/amp/ampiframe.html?AV_TAGID=${playerOptions.aniviewPlayerId}&AV_PUBLISHERID=5fabb425e5d4cb4bbc0ca7e4`,
}
);

if (consentObj['gdpr']) {
ampAvAd['data-av_gdpr'] = consentObj['gdpr'];
ampAvAd['data-av_consent'] = consentObj['user_consent'];
}

const ampAvAdWrap = createElementWithAttributes(
/** @type {!Document} */ (apesterElement.ownerDocument),
'div',
{'class': 'i-amphtml-amp-apester-in-unit-wrap'}
);

const progressBarWrap = createElementWithAttributes(
/** @type {!Document} */ (apesterElement.ownerDocument),
'div',
{'class': 'i-amphtml-amp-apester-progress-bar'}
);
ampAvAdWrap.appendChild(progressBarWrap);
ampAvAdWrap.appendChild(ampAvAd);
apesterElement.appendChild(ampAvAdWrap);

showVideoAd(ampAvAdWrap, progressBarWrap, idleOptions);
const {skipTimer, timeout} = idleOptions;
setInterval(() => {
showVideoAd(ampAvAdWrap, progressBarWrap, idleOptions);
}, (timeout + skipTimer) * 1000);

Services.mutatorForDoc(apesterElement).requestChangeSize(
ampAvAd,
size.height
);
}

/**
* @param {!AmpElement} apesterElement
* @return {{height: number, width: number}}
*/
export function getCompanionVideoAdSize(apesterElement) {
const adWidth = apesterElement./*REVIEW*/ clientWidth;
const adRatio = 0.6;
const adHeight = Math.ceil(adWidth * adRatio);
return {width: adWidth, height: adHeight};
}
8 changes: 5 additions & 3 deletions extensions/amp-apester-media/0.1/monetization/index.js
@@ -1,20 +1,22 @@
import {handleCompanionBottomAd} from './companion/bottomAd';
import {handleBottomAd} from './bottomAd/bottomAd';
import {handleCompanionDisplay} from './companion/display';
import {handleCompanionVideo} from './companion/video';
import {getConsentData} from './consent-util';
import {handleInUnitVideo} from './inUnit/video';

/**
* @param {!JsonObject} media
* @param {!AmpElement} apesterElement
* @return {!Promise}
*/
export function handleCompanionAds(media, apesterElement) {
export function handleAds(media, apesterElement) {
const monetizationSettings = media['campaignData'];
if (monetizationSettings && !monetizationSettings.disabledAmpCompanionAds) {
return getConsentData(apesterElement).then((consentData) => {
handleCompanionDisplay(media, apesterElement);
handleCompanionVideo(media, apesterElement, consentData);
handleCompanionBottomAd(media, apesterElement);
handleBottomAd(media, apesterElement);
handleInUnitVideo(media, apesterElement, consentData);
});
}
return Promise.resolve();
Expand Down

0 comments on commit 8570909

Please sign in to comment.