Skip to content

Commit

Permalink
Merge pull request #752 from Shinsina/story-continues-for-real-this-time
Browse files Browse the repository at this point in the history
Story Continues button with injected ads content (non-gated)
  • Loading branch information
Shinsina authored Oct 3, 2024
2 parents 5739597 + 1b5eb8e commit 740299a
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 5 deletions.
2 changes: 2 additions & 0 deletions packages/global/browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Leaders from '@parameter1/base-cms-marko-web-leaders/browser';
const ImageSlider = () => import(/* webpackChunkName: "global-image-slider" */ './image-slider.vue');
const DynamicSiteMenuPositioner = () => import(/* webpackChunkName: "dynamic-site-menu-positioner" */ './dynamic-site-menu-positioner.vue');
const ReadingProgressBar = () => import(/* webpackChunkName: "cpgnext-reading-progress-bar" */ './reading-progress-bar.vue');
const StoryContinuesButton = () => import(/* webpackChunkName: "story-continues-button" */ './story-continues-button.vue');

export default (Browser) => {
MonoRail(Browser);
Expand All @@ -12,4 +13,5 @@ export default (Browser) => {
Browser.register('DynamicSiteMenuPositioner', DynamicSiteMenuPositioner);
Browser.register('GlobalImageSlider', ImageSlider);
Browser.register('GlobalReadingProgressBar', ReadingProgressBar);
Browser.register('GlobalStoryContinuesButton', StoryContinuesButton);
};
50 changes: 50 additions & 0 deletions packages/global/browser/story-continues-button.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<button
v-if="showButton"
class="btn-primary"
style="margin-bottom: 10px"
@click="handleClick"
>
Story Continues
</button>
</template>

<script>
export default {
data: () => ({
showButton: true,
}),
created() {
this.observer = new IntersectionObserver((event) => {
if (event[0].isIntersecting) {
const { dataLayer } = window;
if (dataLayer) {
const payload = {
event: 'story-continues-button-view',
};
dataLayer.push(payload);
}
}
});
},
mounted() {
this.observer.observe(this.$el);
},
methods: {
handleClick() {
this.showButton = false;
const contentPagePreviewOverlay = document.getElementById('content-page-preview-overlay');
const bodyPartTwo = document.getElementById('content-body-part-two');
contentPagePreviewOverlay.style = 'display: none;';
bodyPartTwo.removeAttribute('style');
const { dataLayer } = window;
if (dataLayer) {
const payload = {
event: 'story-continues-button-click',
};
dataLayer.push(payload);
}
},
},
};
</script>
98 changes: 98 additions & 0 deletions packages/global/components/body-with-injection.marko
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { getAsArray } from "@parameter1/base-cms-object-path";
import defaultValue from "@parameter1/base-cms-marko-core/utils/default-value";
import MarkoWebContentBody from "@parameter1/base-cms-marko-web/components/element/content/body";
import GAMDefineDisplayAd from "@parameter1/base-cms-marko-web-theme-monorail/components/gam/define-display-ad";

$ const { global: $global } = out;
$ const { GAM } = $global;
$ const { content, modifiers } = input;
$ const preventHTMLInjection = getAsArray(content, "labels").some( l => ["Sponsored", "Product Spotlight"].indexOf(l) >= 0) || input.preventHTMLInjection;
$ const blockName = defaultValue(input.blockName, 'page-contents');
$ const aliases = getAsArray(input, 'aliases');
$ const selector = defaultValue(input.selector, `content-body-${content.id}`);

<!-- Desktop Inline Ad props -->
$ const desktopAdCounts = defaultValue(input.desktopAdCounts, [1500, 2750, 4500, 6250, 8000, 9750, 11500, 13250, 15000, 16750, 18500]);
$ const desktopAdName = defaultValue(input.desktopAdName, "inline-content-desktop");
$ const desktopAdModifiers = defaultValue(input.desktopAdModifiers, ["margin-auto-x", "inline-content", "inline-content-desktop"]);
$ const desktopAdDataPropToPreventDupes = defaultValue(input.desktopAdDataPropToPreventDupes, "gamTemplateName");

<!-- Desktop Leaderboard Ad props -->
$ const desktopLeaderboardAdCounts = defaultValue(input.desktopLeaderboardAdCounts, [350]);
$ const desktopLeaderboardAdName = defaultValue(input.desktopLeaderboardAdName, desktopAdName);
$ const desktopLeaderboardAdModifiers = defaultValue(input.desktopLeaderboardAdModifiers, desktopAdModifiers);
$ const desktopLeaderboardAdDataPropToPreventDupes = defaultValue(input.desktopLeaderboardAdDataPropToPreventDupes, desktopAdDataPropToPreventDupes);

<!-- Mobile Inline Ad props -->
$ const mobileAdCounts = defaultValue(input.mobileAdCounts, [900, 1650, 2950, 4250, 5550, 6850, 8150, 9450, 10750, 12050, 13350, 14650, 15950, 17250]);
$ const mobileAdName = defaultValue(input.mobileAdName, "inline-content-mobile");
$ const mobileAdModifiers = defaultValue(input.mobileAdModifiers, ["margin-auto-x", "inline-content", "inline-content-mobile"]);
$ const mobileAdDataPropToPreventDupes = defaultValue(input.mobileAdDataPropToPreventDupes, "gamTemplateName");

<!-- Mobile Leaderboard Ad props || fallback set to 250 & mobileAdProps -->
$ const mobileLeaderboardAdCounts = defaultValue(input.mobileLeaderboardAdCounts, [250]);
$ const mobileLeaderboardAdName = defaultValue(input.mobileLeaderboardAdName, mobileAdName);
$ const mobileLeaderboardAdModifiers = defaultValue(input.mobileLeaderboardAdModifiers, mobileAdModifiers);
$ const mobileLeaderboardAdDataPropToPreventDupes = defaultValue(input.mobileLeaderboarAdDataPropToPreventDupes, mobileAdDataPropToPreventDupes);

<!-- Only set GAM defaults if GAM is present on out.global -->
$ const gamAdInjection = (GAM) ? [
{
counts: desktopLeaderboardAdCounts,
name: desktopLeaderboardAdName,
modifiers: desktopLeaderboardAdModifiers,
dataPropToPreventDupes: desktopLeaderboardAdDataPropToPreventDupes
},
{
counts: desktopAdCounts,
name: desktopAdName,
modifiers: desktopAdModifiers,
dataPropToPreventDupes: desktopAdDataPropToPreventDupes
},
{
counts: mobileLeaderboardAdCounts,
name: mobileLeaderboardAdName,
modifiers: mobileLeaderboardAdModifiers,
dataPropToPreventDupes: mobileLeaderboardAdDataPropToPreventDupes
},
{
counts: mobileAdCounts,
name: mobileAdName,
modifiers: mobileAdModifiers,
dataPropToPreventDupes: mobileAdDataPropToPreventDupes
}
] : [];


<theme-ssr-html-inject
to-render=MarkoWebContentBody
selector=`#${selector}`
>
<@component-input
block-name=blockName
modifiers=modifiers
obj=content
attrs={ id: selector }
embed-options=input.embedOptions
lazyload-first-image=input.lazyloadFirstImage
/>
<if(!preventHTMLInjection)>
<for|adInjection| of=gamAdInjection>
$ const { counts, name, modifiers } = adInjection;
<if(adInjection.counts.length)>
<for|count| of=adInjection.counts>
<@inject
at=count
html=GAMDefineDisplayAd.renderToString({
name,
aliases,
modifiers,
$global
})
dataPropToPreventDupes=adInjection.dataPropToPreventDupes
/>
</for>
</if>
</for>
</if>
</theme-ssr-html-inject>
24 changes: 19 additions & 5 deletions packages/global/components/layouts/content/default.marko
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ import { get, getAsArray } from "@parameter1/base-cms-object-path";
import contentIframe from "@pmmi-media-group/package-global/utils/content-iframe";
import getContentPreview from "@parameter1/base-cms-marko-web-theme-monorail/utils/get-content-preview";
import handleContentTypePrimarySection from "@pmmi-media-group/package-global/utils/handle-content-type-primary-section";
import GlobalBodyWithInjection from "@pmmi-media-group/package-global/components/body-with-injection";
import splitContentBody from "@pmmi-media-group/package-global/utils/split-content-body";

$ const { global: $global } = out;
$ const {
site,
config,
Expand Down Expand Up @@ -169,12 +172,23 @@ $ const shouldInjectAds = ["article", "blog", "news", "podcast", "press-release"
$ const bodyId = `content-body-${content.id}`;

<global-supplier-submitted-block labels=content.labels />
<theme-body-with-injection
content=content
aliases=aliases
$ const contentBodyWithInjections = GlobalBodyWithInjection.renderToString({
content,
aliases,
blockName,
selector: bodyId,
preventHTMLInjection: !shouldInjectAds,
$global
});
$ const { partOne, partTwo } = splitContentBody({ body: contentBodyWithInjections });
<marko-web-content-body block-name=blockName obj={ body: partOne } />
<div id="content-page-preview-overlay" class="content-page-preview-overlay" />
<marko-web-browser-component name="GlobalStoryContinuesButton" />
<marko-web-content-body
block-name=blockName
selector=bodyId
preventHTMLInjection=!shouldInjectAds
obj={ body: partTwo }
attrs={ style: "display: none;", id: "content-body-part-two" }
modifiers=["ld-json"]
/>
<if(content.transcript)>
$ const transcriptId = `content-transcript-${content.id}`;
Expand Down
3 changes: 3 additions & 0 deletions packages/global/components/marko.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,8 @@
"type": "number",
"required": true
}
},
"<global-body-with-injection>": {
"template": "./body-with-injection.marko"
}
}
19 changes: 19 additions & 0 deletions packages/global/utils/split-content-body.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const cheerio = require('cheerio');

module.exports = ({ body } = {}) => {
const $ = cheerio.load(body);
// Suspecting halfway needs to be calculated like quarterway due to injected ads here
const likelyHalfwayElement = Math.floor($('div').children().length / 4);
const part1Nodes = [];
const part2Nodes = [];
$('div').children().each((index, node) => {
if (index < likelyHalfwayElement) {
part1Nodes.push($.html(node));
} else {
part2Nodes.push($.html(node));
}
});
const partOne = part1Nodes.join('');
const partTwo = part2Nodes.join('');
return { partOne, partTwo };
};

0 comments on commit 740299a

Please sign in to comment.