Add outbrain

- Only add for unauthenticated users for now. We can change that to look at premium later without having to touch `app/view.jsx`.

- Only show the ad after knowing the ad is filled; this prevents the invisible container from blocking stuff while waiting, or even worse, when not filled.
This commit is contained in:
infinite-persistence 2022-03-18 08:58:06 +08:00 committed by Thomas Zarebczan
parent d2fdcc970f
commit 802b5d5a18
4 changed files with 80 additions and 2 deletions

View file

@ -2,7 +2,7 @@ import { hot } from 'react-hot-loader/root';
import { connect } from 'react-redux';
import { selectGetSyncErrorMessage, selectSyncFatalError, selectSyncIsLocked } from 'redux/selectors/sync';
import { doUserSetReferrer } from 'redux/actions/user';
import { selectUser, selectUserLocale, selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectOdyseeMembershipIsPremiumPlus, selectUser, selectUserLocale, selectUserVerifiedEmail } from 'redux/selectors/user';
import { selectUnclaimedRewards } from 'redux/selectors/rewards';
import { doFetchChannelListMine, doFetchCollectionListMine, doResolveUris } from 'redux/actions/claims';
import { selectMyChannelClaimIds } from 'redux/selectors/claims';
@ -41,6 +41,7 @@ const select = (state) => ({
activeChannelClaim: selectActiveChannelClaim(state),
myChannelClaimIds: selectMyChannelClaimIds(state),
subscriptions: selectSubscriptions(state),
hasPremiumPlus: selectOdyseeMembershipIsPremiumPlus(state),
});
const perform = (dispatch) => ({

View file

@ -16,6 +16,7 @@ import useKonamiListener from 'util/enhanced-layout';
import Yrbl from 'component/yrbl';
import FileRenderFloating from 'component/fileRenderFloating';
import { withRouter } from 'react-router';
import useAdOutbrain from 'effects/use-ad-outbrain';
import usePrevious from 'effects/use-previous';
import Nag from 'component/common/nag';
import REWARDS from 'rewards';
@ -86,6 +87,7 @@ type Props = {
activeChannelClaim: ?ChannelClaim,
myChannelClaimIds: ?Array<string>,
subscriptions: Array<Subscription>,
hasPremiumPlus: ?boolean,
setActiveChannelIfNotSet: () => void,
setIncognito: (boolean) => void,
fetchModBlockedList: () => void,
@ -125,6 +127,7 @@ function App(props: Props) {
fetchModBlockedList,
resolveUris,
subscriptions,
hasPremiumPlus,
fetchModAmIList,
} = props;
@ -480,6 +483,8 @@ function App(props: Props) {
useDegradedPerformance(setLbryTvApiStatus, user);
useAdOutbrain(Boolean(hasPremiumPlus), isAuthenticated);
useEffect(() => {
// When language is changed or translations are fetched, we render.
setLangRenderKey(Date.now());

View file

@ -0,0 +1,62 @@
// @flow
import React from 'react';
function inIFrame() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
const LOAD_AD_DELAY_MS = 3000; // Wait past boot-up and core-vitals period.
const OUTBRAIN_CONTAINER_KEY = 'outbrainStickyParent';
let script;
export default function useAdOutbrain(hasPremiumPlus: boolean, isAuthenticated: boolean) {
// Only look at authentication for now. Eventually, we'll only use 'hasPremiumPlus'.
const isAuthenticatedRef = React.useRef(isAuthenticated);
isAuthenticatedRef.current = isAuthenticated;
function loadListener() {
const container = window[OUTBRAIN_CONTAINER_KEY];
if (container) {
// Hide it immediately while we wait for ads to be filled. This prevents
// the invisible container from blocking our content.
container.style.visibility = 'hidden';
// Restore visibility after confirming the ad is filled. If it is filled
// after the stipulated time, well, no soup for you.
setTimeout(() => {
const filledAd = document.querySelector('.ob-widget-items-container');
if (filledAd && !isAuthenticatedRef.current) {
container.style.visibility = 'visible';
}
}, 5000); // 3s is sufficient for Chrome, but Firefox seems to take ~5s
}
}
React.useEffect(() => {
if (!inIFrame() && !isAuthenticated && !script) {
const loadTimer = setTimeout(() => {
script = document.createElement('script');
script.src = 'https://adncdnend.azureedge.net/adtags/odysee.adn.js';
script.async = true;
script.addEventListener('load', loadListener); // not using 'script.onload'; seem unreliable with async.
// $FlowFixMe
document.body.appendChild(script);
}, LOAD_AD_DELAY_MS);
return () => clearTimeout(loadTimer);
}
// eslint-disable-next-line react-hooks/exhaustive-deps, (on mount only)
}, []);
React.useEffect(() => {
if (isAuthenticated && window[OUTBRAIN_CONTAINER_KEY]) {
window[OUTBRAIN_CONTAINER_KEY].style.display = 'none';
}
}, [isAuthenticated]);
}

View file

@ -54,7 +54,7 @@
width: $width;
}
div[style*='transform-origin: left bottom;'] {
div[style*='transform-origin: left bottom'] {
// [Floating ad]
// Hide for now since can't get it to work in a consistent manner between:
// - EU and non-EU version
@ -187,3 +187,13 @@
.exp-ui__logo {
display: none;
}
// ****************************************************************************
// Outbrain
// ****************************************************************************
.ob-widget-items-container {
padding-left: var(--spacing-xs);
padding-right: var(--spacing-xs);
border-radius: var(--border-radius);
}