docbrown/app/javascript/packs/billboardAfterRenderActions.js
Ridhwana 8003691b37
Restructure the way we render the feed + add billboard locations on signed in feed (#19652)
* feat: fix of there is no article

* feat: set the feed order in a data structure rather than in a view

* feat: update yarn.lock

* feat: push the items to the array

* feat: update feed to only show billboards if we have the correct length of items in the feed

* fix: organizedFeedItems.legth

* feat: rename 'featured' to 'image'

* feat: rename 'featured' to 'image'

* feat: rename 'featured' to 'image'

* feat: add some utilities for the feed that we can use in the FeedTest

* feat/WIP: the setup for the feed tests and a first working test

* test: imageItem

* fix: the podcasts can be passed through as an array of objects in the feedItems so that they can be grouped in one card

* feat: remove podcastEpisode state and the attribute in the object

* fix: check that the items exist before trying to slice them

* feat: setup the userdata and the podcast data in the test

* whoops - commit the podcast episodes

* feat: write soem more tests for the feed and including the podcasts

* feat: add some more tests

* feat: add more billboards tests to chcek the order of stuff

* feat: set the timeframe not empty

* feat: update the logic for organizaed feed by inserting the last on first

* doc: jsdoc for functions

* refactor: break the code up into smaller functions

* refactor: make the code more readable and easier to follow

* refactor: pull function out into a utlity

* feat: add specs to utility

* feat: chcek if pinned post

* test the latest timeframe correctly

* chore: update var name

* move the podcast items out of the object clause

* feat: update text

* feat: add a pack file that duplicates initializeDisplayAdVisibility

* feat: create callbacks that will help us to determine when the feed has been rendered so that we can observe the dsplay ads accordingly

* chore: rename to billboards instead of display ad

* feat: first pass at some error handling whilst maintaining the order of the items

* test: for feed error

* feat: abstract out some code

* update the feed items for errors

* chore: comment

* feat: update the variable names

* feat: update honeybadger message
2023-07-03 15:00:44 +02:00

117 lines
3 KiB
JavaScript

/* global userData */
// This is currently a duplicate of app/assets/javascript/initializers/initializeDisplayAdVisibility.
export function initializeDisplayAdVisibility() {
const displayAds = document.querySelectorAll('[data-display-unit]');
if (displayAds && displayAds.length == 0) {
return;
}
const user = userData();
displayAds.forEach((ad) => {
if (user && !user.display_sponsors && ad.dataset['typeOf'] == 'external') {
ad.classList.add('hidden');
} else {
ad.classList.remove('hidden');
}
});
}
export function observeDisplayAds() {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const elem = entry.target;
if (entry.intersectionRatio >= 0.25) {
setTimeout(() => {
trackAdImpression(elem);
}, 1);
}
}
});
},
{
root: null, // defaults to browser viewport
rootMargin: '0px',
threshold: 0.25,
},
);
document.querySelectorAll('[data-display-unit]').forEach((ad) => {
observer.observe(ad);
ad.removeEventListener('click', trackAdClick, false);
ad.addEventListener('click', () => trackAdClick(ad));
});
}
function trackAdImpression(adBox) {
const isBot =
/bot|google|baidu|bing|msn|duckduckbot|teoma|slurp|yandex/i.test(
navigator.userAgent,
); // is crawler
const adSeen = adBox.dataset.impressionRecorded;
if (isBot || adSeen) {
return;
}
const tokenMeta = document.querySelector("meta[name='csrf-token']");
const csrfToken = tokenMeta && tokenMeta.getAttribute('content');
const dataBody = {
display_ad_event: {
display_ad_id: adBox.dataset.id,
context_type: adBox.dataset.contextType,
category: adBox.dataset.categoryImpression,
},
};
window
.fetch('/display_ad_events', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify(dataBody),
credentials: 'same-origin',
})
.catch((error) => console.error(error));
adBox.dataset.impressionRecorded = true;
}
function trackAdClick(adBox) {
const isBot =
/bot|google|baidu|bing|msn|duckduckbot|teoma|slurp|yandex/i.test(
navigator.userAgent,
); // is crawler
const adClicked = adBox.dataset.clickRecorded;
if (isBot || adClicked) {
return;
}
const tokenMeta = document.querySelector("meta[name='csrf-token']");
const csrfToken = tokenMeta && tokenMeta.getAttribute('content');
const dataBody = {
display_ad_event: {
display_ad_id: adBox.dataset.id,
context_type: adBox.dataset.contextType,
category: adBox.dataset.categoryClick,
},
};
window.fetch('/display_ad_events', {
method: 'POST',
headers: {
'X-CSRF-Token': csrfToken,
'Content-Type': 'application/json',
},
body: JSON.stringify(dataBody),
credentials: 'same-origin',
});
adBox.dataset.clickRecorded = true;
}