-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c401c63
commit ad51d6a
Showing
12 changed files
with
530 additions
and
263 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
246 changes: 246 additions & 0 deletions
246
extensions/amp-apester-media/0.1/monetization/ads-constructor.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
import {createElementWithAttributes} from '#core/dom'; | ||
import {setStyle} from '#core/dom/style'; | ||
import {Services} from '#service'; | ||
|
||
import {defaultRefreshTime, AD_TYPES, defaultBannerSizes} from './consent-util'; | ||
|
||
/** | ||
* @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}; | ||
} | ||
|
||
/** | ||
* @param {!AmpElement} apesterElement | ||
* @param {{height: number, width: number}} size | ||
* @param {string} aniviewPlayerId | ||
* @param {!JsonObject} consentObj | ||
* @param {string} publisherId | ||
* @return {!Element} | ||
*/ | ||
export function getAniviewAdElement(apesterElement, size, aniviewPlayerId, consentObj, publisherId) { | ||
publisherId = publisherId || '5fabb425e5d4cb4bbc0ca7e4'; | ||
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, | ||
'src': `https://player.avplayer.com/amp/ampiframe.html?AV_TAGID=${aniviewPlayerId}&AV_PUBLISHERID=${publisherId}`, | ||
} | ||
); | ||
|
||
if (consentObj?.gdpr) { | ||
ampAvAd['data-av_gdpr'] = consentObj['gdpr']; | ||
ampAvAd['data-av_consent'] = consentObj['user_consent']; | ||
} | ||
return ampAvAd; | ||
} | ||
|
||
/** | ||
* @param {!AmpElement} apesterElement | ||
* @param {string} aniviewPlayerId | ||
* @param {!JsonObject} consentObj | ||
* @param {boolean} isAbove | ||
* @param {string} publisherId | ||
* @return {!Element} | ||
*/ | ||
export function constructStaticAniviewAd(apesterElement, aniviewPlayerId, consentObj, isAbove, publisherId) { | ||
const size = getCompanionVideoAdSize(apesterElement); | ||
const ampAvAd = getAniviewAdElement(apesterElement, size, aniviewPlayerId, consentObj, publisherId); | ||
|
||
ampAvAd.classList.add('i-amphtml-amp-apester-companion'); | ||
|
||
apesterElement.parentNode.insertBefore(ampAvAd, isAbove ? apesterElement : apesterElement.nextSibling); | ||
|
||
Services.mutatorForDoc(apesterElement).requestChangeSize( | ||
ampAvAd, | ||
size.height | ||
); | ||
} | ||
|
||
/** | ||
* @param {string} slot | ||
* @param {Array} bannerSizes | ||
* @param {!AmpElement} apesterElement | ||
* @param {number} refreshInterval | ||
* @param {!JsonObject} rtcConfig | ||
* @param {!boolean} isAbove | ||
* @return {!Element} | ||
*/ | ||
export function constructStaticDisplayAd( | ||
slot, | ||
bannerSizes, | ||
apesterElement, | ||
refreshInterval, | ||
rtcConfig, | ||
isAbove, | ||
) { | ||
const maxWidth = Math.max.apply( | ||
null, | ||
bannerSizes.map((s) => s[0]) | ||
); | ||
const maxHeight = Math.max.apply( | ||
null, | ||
bannerSizes.map((s) => s[1]) | ||
); | ||
|
||
const multiSizeData = bannerSizes.map((size) => size.join('x')).join(); | ||
const ampAd = createElementWithAttributes( | ||
/** @type {!Document} */ (apesterElement.ownerDocument), | ||
'amp-ad', | ||
{ | ||
'width': `${maxWidth}`, | ||
'height': `${maxHeight}`, | ||
'type': 'doubleclick', | ||
'layout': 'fixed', | ||
'data-slot': `${slot}`, | ||
'data-multi-size-validation': 'false', | ||
'data-multi-size': multiSizeData, | ||
'data-enable-refresh': `${refreshInterval}`, | ||
} | ||
); | ||
if (rtcConfig) { | ||
ampAd.setAttribute('rtc-config', JSON.stringify(rtcConfig)); | ||
} | ||
ampAd.classList.add('i-amphtml-amp-apester-companion'); | ||
apesterElement.parentNode.insertBefore(ampAd, isAbove ? apesterElement : apesterElement.nextSibling); | ||
Services.mutatorForDoc(apesterElement).requestChangeSize( | ||
ampAd, | ||
maxHeight, | ||
/* newWidth */ undefined | ||
); | ||
return ampAd; | ||
} | ||
|
||
/** | ||
* @param {string} slot | ||
* @param {Array} bannerSizes | ||
* @param {!AmpElement} apesterElement | ||
* @param {!JsonObject} rtcConfig | ||
* @return {!Element} | ||
*/ | ||
export function constructBottomAd( | ||
slot, | ||
apesterElement, | ||
rtcConfig | ||
) { | ||
const height = 50; | ||
const ampAd = createElementWithAttributes( | ||
/** @type {!Document} */ (apesterElement.ownerDocument), | ||
'amp-ad', | ||
{ | ||
'width': '300', | ||
'height': `${height}`, | ||
'type': 'doubleclick', | ||
'layout': 'fixed', | ||
'data-slot': `${slot}`, | ||
'data-multi-size-validation': 'false', | ||
'data-enable-refresh': `${defaultRefreshTime}`, | ||
} | ||
); | ||
if (rtcConfig) { | ||
ampAd.setAttribute('rtc-config', JSON.stringify(rtcConfig)); | ||
} | ||
ampAd.classList.add('i-amphtml-amp-apester-bottom-ad'); | ||
apesterElement.appendChild(ampAd); | ||
Services.mutatorForDoc(apesterElement).requestChangeSize(ampAd, height); | ||
return ampAd; | ||
} | ||
|
||
|
||
/** | ||
* @param {!AmpElement} adWrap | ||
* @param {!AmpElement} progressBar | ||
* @param {!JsonObject} refreshOptions | ||
*/ | ||
function showInUnitAd(adWrap, progressBar, refreshOptions) { | ||
const {skipTimer, timeInView} = refreshOptions; | ||
const showTime = timeInView || skipTimer; | ||
adWrap.classList.add('active'); | ||
setStyle(progressBar, 'animation', `progress ${showTime}s linear 1`); | ||
const timer = setTimeout(() => { | ||
adWrap.classList.remove('active'); | ||
clearTimeout(timer); | ||
}, showTime * 1000); | ||
} | ||
|
||
/** | ||
* @param {string} mediaType | ||
* @param {string} aniviewPlayerIdOrAdUnit | ||
* @param {!AmpElement} apesterElement | ||
* @param {!JsonObject} consentObj | ||
* @param {!JsonObject} refreshOptions | ||
* @param {string} publisherId | ||
* @param {!JsonObject} rtcConfig | ||
*/ | ||
export function constructInUnitAd(mediaType, aniviewPlayerIdOrAdUnit, apesterElement, consentObj, refreshOptions, publisherId, rtcConfig) { | ||
let size; | ||
let ampAvAd; | ||
const {skipTimer, timeout, timeInView, timeBetweenAds} = refreshOptions; | ||
const refreshTime = ((timeBetweenAds || timeout || 20) + (timeInView || skipTimer)) * 1000; | ||
if (mediaType === AD_TYPES.video) { | ||
size = getCompanionVideoAdSize(apesterElement); | ||
ampAvAd = getAniviewAdElement(apesterElement, size, aniviewPlayerIdOrAdUnit, consentObj, publisherId); | ||
} else { | ||
size = {width: 300, height: 250}; | ||
ampAvAd = createElementWithAttributes( | ||
/** @type {!Document} */ (apesterElement.ownerDocument), | ||
'amp-ad', | ||
{ | ||
'width': `${size.width}`, | ||
'height': `${size.height}`, | ||
'type': 'doubleclick', | ||
'layout': 'fixed', | ||
'data-slot': `${aniviewPlayerIdOrAdUnit}`, | ||
'data-multi-size-validation': 'false', | ||
'data-enable-refresh': `${refreshTime}`, | ||
} | ||
); | ||
if (rtcConfig) { | ||
ampAd.setAttribute('rtc-config', JSON.stringify(rtcConfig)); | ||
} | ||
} | ||
|
||
ampAvAd.classList.add('i-amphtml-amp-apester-in-unit'); | ||
|
||
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); | ||
|
||
showInUnitAd(ampAvAdWrap, progressBarWrap, refreshOptions); | ||
setInterval( | ||
() => { | ||
showInUnitAd(ampAvAdWrap, progressBarWrap, refreshOptions); | ||
}, | ||
refreshTime | ||
); | ||
|
||
Services.mutatorForDoc(apesterElement).requestChangeSize( | ||
ampAvAd, | ||
size.height | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import {getValueForExpr} from '#core/types/object'; | ||
|
||
import { | ||
constructStaticDisplayAd, | ||
constructStaticAniviewAd, | ||
constructBottomAd, | ||
constructInUnitAd | ||
} from './ads-constructor'; | ||
import {PLACAMENT_POSITIONS, AD_TYPES, defaultBannerSizes, defaultRefreshTime} from './consent-util'; | ||
|
||
|
||
/** | ||
* @param {!JsonObject} media | ||
* @param {!AmpElement} apesterElement | ||
* @param {!JsonObject} consentObj | ||
*/ | ||
export function handleAdsetAds(media, apesterElement, consentObj) { | ||
// check if adset settings is set | ||
const adsetData = getValueForExpr( | ||
/**@type {!JsonObject}*/ (media), | ||
'adsetData' | ||
); | ||
const adsetPlacements = adsetData?.placements; | ||
if (!adsetPlacements?.length) { | ||
return; | ||
} | ||
const staticSettings = adsetData.settings?.staticAds || {}; | ||
const inUnitSettings = adsetData.settings?.inUnit || {}; | ||
|
||
adsetPlacements.forEach((adPlacement) => { | ||
const adData = adPlacement.ads[0]; | ||
const adProvider = adData?.provider; | ||
const adUnit = adProvider?.adUnit; | ||
const aniviewPlayerId = adProvider?.playerId; | ||
const rtcConfig = adProvider?.rtcConfig; | ||
|
||
// static ads above or below | ||
if ([PLACAMENT_POSITIONS.above, PLACAMENT_POSITIONS.below].includes(adPlacement.type)) { | ||
const isAbove = adPlacement.type === PLACAMENT_POSITIONS.above; | ||
|
||
if (adUnit && adData.mediaType === AD_TYPES.display) { | ||
const refreshInterval = staticSettings?.refresh?.refreshTime || defaultRefreshTime; | ||
const bannerSizes = adProvider.sizes || defaultBannerSizes; | ||
constructStaticDisplayAd( | ||
adUnit, | ||
bannerSizes, | ||
apesterElement, | ||
refreshInterval, | ||
rtcConfig, | ||
isAbove | ||
); | ||
} else if (aniviewPlayerId && adData.mediaType === AD_TYPES.video) { | ||
constructStaticAniviewAd( | ||
apesterElement, | ||
aniviewPlayerId, | ||
consentObj, | ||
isAbove, | ||
adProvider?.publisherId | ||
); | ||
} | ||
} | ||
|
||
// bottom Ad | ||
if (adPlacement.type === PLACAMENT_POSITIONS.bottom && adUnit) { | ||
constructBottomAd(adUnit, apesterElement, rtcConfig); | ||
} | ||
|
||
// inUnit Ad | ||
if (adPlacement.type === PLACAMENT_POSITIONS.in_unit && (adUnit || aniviewPlayerId)) { | ||
constructInUnitAd( | ||
adData.mediaType, | ||
adData.mediaType === AD_TYPES.display ? adUnit : aniviewPlayerId, | ||
apesterElement, | ||
consentObj, | ||
inUnitSettings, | ||
adProvider?.publisherId, | ||
rtcConfig | ||
); | ||
} | ||
}); | ||
} |
Oops, something went wrong.