@schibsted/niche-ads
Advanced tools
Comparing version 2.0.2 to 3.0.0
@@ -0,1 +1,21 @@ | ||
## [3.0.0](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/compare/v2.0.2...v3.0.0) (2023-02-28) | ||
### ⚠ BREAKING CHANGES | ||
- remove loggingEnabled option | ||
- chore: fix typos | ||
### Miscellaneous Chores | ||
- update commitlint monorepo to ^17.4.2 ([#94](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/94)) ([fc1b5f0](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/fc1b5f0ebdeca767cf221adec6e58d355869221a)) | ||
- update dependency @babel/core to ^7.20.12 ([#93](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/93)) ([e1b1592](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/e1b15922a2bb81eaef91bf233369fd1b7bb1aa5f)) | ||
- update dependency husky to ^8.0.3 ([#92](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/92)) ([30e0356](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/30e03564e63bfe25fec85166ab5c46ba1e32a1c4)) | ||
- update dependency lint-staged to ^13.1.2 ([#96](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/96)) ([59039d2](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/59039d23f7c2b21b53657efbb28c84bdd6644e05)) | ||
- update linters ([#91](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/91)) ([ecc135f](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/ecc135f8c90d7b43fbb7735b4ea6882d018e1d81)) | ||
### Code Refactoring | ||
- general refactor of the context ([#99](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/issues/99)) ([7b42457](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/commit/7b42457b901e72a284cdb84486dad3a98822e4f9)) | ||
### [2.0.2](https://github.schibsted.io/przemyslaw-babiarz/niche-ads/compare/v2.0.1...v2.0.2) (2023-01-03) | ||
@@ -2,0 +22,0 @@ |
@@ -53,36 +53,33 @@ "use strict"; | ||
} = _ref; | ||
const [placementsConfig, setPlacementsConfig] = (0, _react.useState)([]); | ||
const [placements, setPlacements] = (0, _react.useState)({}); | ||
const [adScriptsReady, setAdScriptsReady] = (0, _react.useState)(false); | ||
const adScriptsReadyRef = (0, _react.useRef)(false); | ||
const placementsConfigRef = (0, _react.useRef)(); | ||
const adScriptsReady = (0, _react.useRef)(false); | ||
const placements = (0, _react.useRef)({}); | ||
const placementsConfig = (0, _react.useRef)([]); | ||
const placementsMediation = (0, _react.useRef)({}); | ||
const retryLoadAds = (0, _react.useRef)(false); | ||
const scriptsLoadPromise = (0, _react.useRef)(); | ||
const logger = (0, _react.useCallback)(error => { | ||
if (adsConfig.loggingEnabled) { | ||
console.log(error); | ||
} | ||
}, [adsConfig.loggingEnabled]); | ||
const hasClearPlacementsBeenCalledLast = (0, _react.useRef)(false); | ||
const adsEventTarget = (0, _react.useRef)(new EventTarget()); | ||
const sendEvent = (0, _react.useCallback)((targetId, placement, placementConfig) => { | ||
adsEventTarget.current.dispatchEvent(new CustomEvent(targetId, { | ||
detail: { | ||
placement, | ||
placementConfig | ||
} | ||
})); | ||
}, []); | ||
(0, _react.useEffect)(() => { | ||
adScriptsReadyRef.current = adScriptsReady; | ||
}, [adScriptsReady]); | ||
(0, _react.useEffect)(() => { | ||
placementsConfigRef.current = placementsConfig; | ||
}, [placementsConfig]); | ||
const adReadyObserver = (0, _useEvent.default)(ready => { | ||
setAdScriptsReady(ready); | ||
}); | ||
(0, _react.useEffect)(() => { | ||
scriptsLoadPromise.current = Promise.all([(0, _loadScript.default)(cdn, 'adsScript'), (0, _loadScript.default)(cogwheelCdn, 'cogwheelScript')]).then(() => { | ||
if (!(0, _appnexus.isASTLoaded)()) { | ||
(0, _appnexus.setUpAPNObject)(); | ||
} | ||
(0, _appnexus.subscribeToASTLoad)(adReadyObserver); | ||
resolveAdBlockerDetectedPromise(false); | ||
}).catch(() => { | ||
resolveAdBlockerDetectedPromise(true); | ||
return null; | ||
// resends data to newly attached palacements that use usePlacement | ||
adsEventTarget.current.addEventListener('resend', e => { | ||
const targetId = e.detail; | ||
sendEvent(targetId, placements.current[targetId] ?? hasClearPlacementsBeenCalledLast.current ? null : undefined, placementsConfig.current.find(p => p.targetId === targetId)); | ||
}); | ||
}, [cdn, cogwheelCdn, adReadyObserver]); | ||
// broadcast data to all listeners in case they attached before this useEffect ran | ||
placementsConfig.current.forEach(placementConfig => { | ||
const targetId = placementConfig.targetId; | ||
sendEvent(targetId, placements.current[targetId] ?? hasClearPlacementsBeenCalledLast.current ? null : undefined, placementsConfig.current.find(p => p.targetId === targetId)); | ||
}); | ||
}, [sendEvent]); | ||
// handles messages sent by ads library on window object | ||
const messageHandler = (0, _useEvent.default)(async event => { | ||
@@ -95,2 +92,4 @@ if (wallpaper.enabled) { | ||
}); | ||
// attaches listener for ads messages on window object | ||
(0, _react.useEffect)(() => { | ||
@@ -109,4 +108,5 @@ window.addEventListener('message', messageHandler); | ||
} = _ref2; | ||
hasClearPlacementsBeenCalledLast.current = false; | ||
await scriptsLoadPromise.current; | ||
if (!device || !adScriptsReadyRef.current) { | ||
if (!device || !adScriptsReady.current) { | ||
retryLoadAds.current = { | ||
@@ -121,3 +121,9 @@ pageType, | ||
retryLoadAds.current = false; | ||
setPlacements({}); | ||
// clear current ads | ||
placements.current = {}; | ||
placementsConfig.current.forEach(placementConfig => { | ||
sendEvent(placementConfig.targetId, undefined); // undefined to mark ads as not loaded yet | ||
}); | ||
placementsMediation.current = {}; | ||
@@ -157,14 +163,15 @@ (0, _appnexus.clearRequest)(); | ||
} | ||
setPlacementsConfig(newPlacementConfig); | ||
}); | ||
(0, _react.useEffect)(() => { | ||
if (retryLoadAds.current) { | ||
const params = retryLoadAds.current; | ||
retryLoadAds.current = false; | ||
loadAds(params); | ||
} | ||
}, [device, loadAds, adScriptsReady]); | ||
(0, _react.useEffect)(() => { | ||
if (placementsConfig?.length > 0) { | ||
const placementsConfigsChunks = (0, _splitEvery.default)(APPNEXUS_PLACEMENTS_PER_REQUEST_LIMIT, placementsConfig); | ||
placementsConfig.current.forEach(placementConfig => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
}); | ||
placementsConfig.current = newPlacementConfig; | ||
if (placementsConfig.current?.length > 0) { | ||
const placementsConfigsChunks = (0, _splitEvery.default)(APPNEXUS_PLACEMENTS_PER_REQUEST_LIMIT, placementsConfig.current); | ||
const setPlacement = (placement, placementConfig) => { | ||
placements.current = { | ||
...placements.current, | ||
[placementConfig.targetId]: placement | ||
}; | ||
sendEvent(placementConfig.targetId, placement, placementConfig); | ||
}; | ||
placementsConfigsChunks.forEach(placementsConfigChunk => { | ||
@@ -181,61 +188,25 @@ placementsConfigChunk.forEach(placementConfig => { | ||
if (placementsMediation.current[placementConfig.targetId] && data.source !== 'csm') { | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: data | ||
})); | ||
setPlacement(data, placementConfig); | ||
} | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adAvailable, placementConfig.targetId, data => { | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: data | ||
})); | ||
setPlacement(data, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adBadRequest, placementConfig.targetId, error => { | ||
logger({ | ||
error, | ||
placementConfig | ||
}); | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: null | ||
})); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adBadRequest, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adError, placementConfig.targetId, error => { | ||
logger({ | ||
error, | ||
placementConfig | ||
}); | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: null | ||
})); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adError, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adCollapse, placementConfig.targetId, () => { | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: null | ||
})); | ||
setPlacement(null, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adNoBid, placementConfig.targetId, () => { | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: null | ||
})); | ||
setPlacement(null, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adRequestFailure, placementConfig.targetId, error => { | ||
logger({ | ||
error, | ||
placementConfig | ||
}); | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: null | ||
})); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adRequestFailure, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
(0, _appnexus.onEvent)(_appnexus.APPNEXUS_EVENT_TYPES.adRequested, placementConfig.targetId, () => { | ||
setPlacements(state => ({ | ||
...state, | ||
[placementConfig.targetId]: undefined | ||
})); | ||
setPlacement(undefined, placementConfig); | ||
}); | ||
@@ -245,25 +216,47 @@ }); | ||
}); | ||
return () => { | ||
placementsConfig.forEach(placementConfig => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
}); | ||
}; | ||
} | ||
return noop; | ||
}, [placementsConfig, adsConfig?.placements?.common]); | ||
}); | ||
const handleLoadAdsReload = (0, _useEvent.default)(() => { | ||
if (retryLoadAds.current) { | ||
const params = retryLoadAds.current; | ||
retryLoadAds.current = false; | ||
loadAds(params); | ||
} | ||
}); | ||
// handles edge case when devie changes from undefined to something useful | ||
(0, _react.useEffect)(() => { | ||
handleLoadAdsReload(); | ||
}, [device, handleLoadAdsReload]); | ||
const clearPlacements = (0, _useEvent.default)(() => { | ||
placementsConfigRef.current?.forEach(placementConfig => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
hasClearPlacementsBeenCalledLast.current = true; | ||
placementsConfig.current.forEach(placementConfig => { | ||
sendEvent(placementConfig.targetId, null); // null to collapse all placements | ||
}); | ||
setPlacements({}); | ||
setPlacementsConfig([]); | ||
placements.current = {}; | ||
placementsConfig.current = []; | ||
placementsMediation.current = {}; | ||
}); | ||
(0, _react.useEffect)(() => { | ||
scriptsLoadPromise.current = Promise.all([(0, _loadScript.default)(cdn, 'adsScript'), (0, _loadScript.default)(cogwheelCdn, 'cogwheelScript')]).then(() => { | ||
if (!(0, _appnexus.isASTLoaded)()) { | ||
(0, _appnexus.setUpAPNObject)(); | ||
} | ||
(0, _appnexus.subscribeToASTLoad)(ready => { | ||
adScriptsReady.current = ready; | ||
handleLoadAdsReload(); | ||
}); | ||
resolveAdBlockerDetectedPromise(false); | ||
}).catch(() => { | ||
resolveAdBlockerDetectedPromise(true); | ||
return null; | ||
}); | ||
}, [cdn, cogwheelCdn, handleLoadAdsReload]); | ||
const value = (0, _react.useMemo)(() => ({ | ||
loadAds, | ||
clearPlacements, | ||
placementsConfig, | ||
placements, | ||
logger, | ||
adBlockerDetectedPromise | ||
}), [placementsConfig, loadAds, placements, clearPlacements, logger]); | ||
adBlockerDetectedPromise, | ||
adsEventTarget: adsEventTarget.current | ||
}), [loadAds, clearPlacements]); | ||
return /*#__PURE__*/(0, _jsxRuntime.jsx)(AdContext.Provider, { | ||
@@ -294,3 +287,2 @@ value: value, | ||
}).isRequired, | ||
loggingEnabled: _propTypes.default.bool, | ||
keywords: _propTypes.default.shape({ | ||
@@ -297,0 +289,0 @@ common: _propTypes.default.shape({ |
@@ -14,7 +14,24 @@ "use strict"; | ||
const { | ||
placementsConfig, | ||
placements | ||
adsEventTarget | ||
} = (0, _react.useContext)(_AdContext.default); | ||
const placementConfig = placementsConfig.find(p => p.targetId === targetId); | ||
const placement = placements[targetId]; | ||
const [placement, setPlacement] = (0, _react.useState)(); | ||
const [placementConfig, setPlacementConfig] = (0, _react.useState)(); | ||
(0, _react.useEffect)(() => { | ||
const listener = e => { | ||
const data = e.detail; | ||
setPlacement(data.placement); | ||
// placementConfig doesn't change so we save some computation not sending it when clearing placements | ||
if (data.placementConfig) { | ||
setPlacementConfig(data.placementConfig); | ||
} | ||
}; | ||
adsEventTarget.addEventListener(targetId, listener); | ||
adsEventTarget.dispatchEvent(new CustomEvent('resend', { | ||
detail: targetId | ||
})); | ||
return () => { | ||
adsEventTarget.removeEventListener(targetId, listener); | ||
}; | ||
}, [adsEventTarget, targetId]); | ||
const showAd = (0, _useEvent.default)(() => { | ||
@@ -25,5 +42,5 @@ if (placement?.targetId) { | ||
}); | ||
return (0, _react.useMemo)(() => [placement, showAd, placementConfig], [placement, showAd, placementConfig]); | ||
return (0, _react.useMemo)(() => [placement, showAd, placementConfig], [placement, placementConfig, showAd]); | ||
}; | ||
var _default = usePlacement; | ||
exports.default = _default; |
{ | ||
"name": "@schibsted/niche-ads", | ||
"version": "2.0.2", | ||
"version": "3.0.0", | ||
"description": "Package containing ads logic reappearing across our projects", | ||
@@ -33,21 +33,21 @@ "main": "dist/index.js", | ||
"@babel/cli": "^7.20.7", | ||
"@babel/core": "^7.20.7", | ||
"@babel/core": "^7.20.12", | ||
"@babel/eslint-parser": "^7.19.1", | ||
"@babel/preset-env": "^7.20.2", | ||
"@babel/preset-react": "^7.18.6", | ||
"@commitlint/cli": "^17.3.0", | ||
"@commitlint/config-conventional": "^17.3.0", | ||
"@commitlint/cli": "^17.4.2", | ||
"@commitlint/config-conventional": "^17.4.2", | ||
"@release-it/conventional-changelog": "^5.1.1", | ||
"eslint": "^8.31.0", | ||
"eslint": "^8.33.0", | ||
"eslint-config-airbnb": "^19.0.4", | ||
"eslint-config-prettier": "^8.5.0", | ||
"eslint-config-prettier": "^8.6.0", | ||
"eslint-plugin-babel": "^5.3.1", | ||
"eslint-plugin-import": "^2.26.0", | ||
"eslint-plugin-jsx-a11y": "^6.6.1", | ||
"eslint-plugin-import": "^2.27.5", | ||
"eslint-plugin-jsx-a11y": "^6.7.1", | ||
"eslint-plugin-prettier": "^4.2.1", | ||
"eslint-plugin-react": "^7.31.11", | ||
"eslint-plugin-react": "^7.32.2", | ||
"eslint-plugin-react-hooks": "^4.6.0", | ||
"husky": "^8.0.2", | ||
"lint-staged": "^13.1.0", | ||
"prettier": "^2.8.1", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^13.1.2", | ||
"prettier": "^2.8.3", | ||
"prop-types": "^15.8.1", | ||
@@ -54,0 +54,0 @@ "release-it": "^15.6.0", |
@@ -70,3 +70,3 @@ # Niche ads | ||
Ideally you won't ever need to use this directly. It may be usefull for debugging or to peek what the library is storing under the hood. Ideally you should use `AdContextProvider`. | ||
Ideally you won't ever need to use this directly. It may be usefull for debugging or to peek what the library is storing under the hood. Ideally you should use `AdContextProvider`. One thing you may find useful there is `adBlockerDetectedPromise` that is a promise that resolves to a boolean and states whether we suspect that adblock was used (we weren't able to load ad script). | ||
@@ -96,3 +96,2 @@ ### AdContextProvider | ||
- **device** - required - string - one of `desktop`, `tablet`, `mobile` | ||
- **loggingEnabled** - optional - boolean - determines if logging is enabled | ||
- **adsConfig** - required - object - ads configuration object | ||
@@ -122,3 +121,2 @@ - **options** - required - object | ||
}, | ||
loggingEnabled: false, | ||
placements: { | ||
@@ -125,0 +123,0 @@ common: { |
@@ -1,2 +0,2 @@ | ||
import { createContext, useMemo, useState, useRef, useEffect, useCallback } from 'react'; | ||
import { createContext, useMemo, useRef, useEffect, useCallback } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
@@ -52,55 +52,48 @@ import splitEvery from './utils/splitEvery'; | ||
function AdContextProvider({ adsConfig, cdn, children, cogwheelCdn, device, wallpaper, glimr }) { | ||
const [placementsConfig, setPlacementsConfig] = useState([]); | ||
const [placements, setPlacements] = useState({}); | ||
const [adScriptsReady, setAdScriptsReady] = useState(false); | ||
const adScriptsReadyRef = useRef(false); | ||
const placementsConfigRef = useRef(); | ||
const adScriptsReady = useRef(false); | ||
const placements = useRef({}); | ||
const placementsConfig = useRef([]); | ||
const placementsMediation = useRef({}); | ||
const retryLoadAds = useRef(false); | ||
const scriptsLoadPromise = useRef(); | ||
const hasClearPlacementsBeenCalledLast = useRef(false); | ||
const adsEventTarget = useRef(new EventTarget()); | ||
const logger = useCallback( | ||
(error) => { | ||
if (adsConfig.loggingEnabled) { | ||
console.log(error); | ||
} | ||
}, | ||
[adsConfig.loggingEnabled] | ||
); | ||
const sendEvent = useCallback((targetId, placement, placementConfig) => { | ||
adsEventTarget.current.dispatchEvent( | ||
new CustomEvent(targetId, { | ||
detail: { | ||
placement, | ||
placementConfig, | ||
}, | ||
}) | ||
); | ||
}, []); | ||
useEffect(() => { | ||
adScriptsReadyRef.current = adScriptsReady; | ||
}, [adScriptsReady]); | ||
// resends data to newly attached palacements that use usePlacement | ||
adsEventTarget.current.addEventListener('resend', (e) => { | ||
const targetId = e.detail; | ||
sendEvent( | ||
targetId, | ||
placements.current[targetId] ?? hasClearPlacementsBeenCalledLast.current ? null : undefined, | ||
placementsConfig.current.find((p) => p.targetId === targetId) | ||
); | ||
}); | ||
useEffect(() => { | ||
placementsConfigRef.current = placementsConfig; | ||
}, [placementsConfig]); | ||
// broadcast data to all listeners in case they attached before this useEffect ran | ||
placementsConfig.current.forEach((placementConfig) => { | ||
const targetId = placementConfig.targetId; | ||
sendEvent( | ||
targetId, | ||
placements.current[targetId] ?? hasClearPlacementsBeenCalledLast.current ? null : undefined, | ||
placementsConfig.current.find((p) => p.targetId === targetId) | ||
); | ||
}); | ||
}, [sendEvent]); | ||
const adReadyObserver = useEvent((ready) => { | ||
setAdScriptsReady(ready); | ||
}); | ||
useEffect(() => { | ||
scriptsLoadPromise.current = Promise.all([ | ||
loadScript(cdn, 'adsScript'), | ||
loadScript(cogwheelCdn, 'cogwheelScript'), | ||
]) | ||
.then(() => { | ||
if (!isASTLoaded()) { | ||
setUpAPNObject(); | ||
} | ||
subscribeToASTLoad(adReadyObserver); | ||
resolveAdBlockerDetectedPromise(false); | ||
}) | ||
.catch(() => { | ||
resolveAdBlockerDetectedPromise(true); | ||
return null; | ||
}); | ||
}, [cdn, cogwheelCdn, adReadyObserver]); | ||
// handles messages sent by ads library on window object | ||
const messageHandler = useEvent(async (event) => { | ||
if (wallpaper.enabled) { | ||
const attachWallpaperImageToPageBody = await import('./appnexusMessageHandlers/wallpaper'); | ||
attachWallpaperImageToPageBody.default(event, wallpaper); | ||
@@ -111,2 +104,3 @@ } | ||
// attaches listener for ads messages on window object | ||
useEffect(() => { | ||
@@ -121,5 +115,6 @@ window.addEventListener('message', messageHandler); | ||
const loadAds = useEvent(async ({ pageType, keywords, allowlist, blocklist }) => { | ||
hasClearPlacementsBeenCalledLast.current = false; | ||
await scriptsLoadPromise.current; | ||
if (!device || !adScriptsReadyRef.current) { | ||
if (!device || !adScriptsReady.current) { | ||
retryLoadAds.current = { pageType, keywords, allowlist, blocklist }; | ||
@@ -131,3 +126,8 @@ | ||
retryLoadAds.current = false; | ||
setPlacements({}); | ||
// clear current ads | ||
placements.current = {}; | ||
placementsConfig.current.forEach((placementConfig) => { | ||
sendEvent(placementConfig.targetId, undefined); // undefined to mark ads as not loaded yet | ||
}); | ||
placementsMediation.current = {}; | ||
@@ -170,17 +170,17 @@ clearRequest(); | ||
} | ||
setPlacementsConfig(newPlacementConfig); | ||
}); | ||
useEffect(() => { | ||
if (retryLoadAds.current) { | ||
const params = retryLoadAds.current; | ||
retryLoadAds.current = false; | ||
loadAds(params); | ||
} | ||
}, [device, loadAds, adScriptsReady]); | ||
placementsConfig.current.forEach((placementConfig) => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
}); | ||
useEffect(() => { | ||
if (placementsConfig?.length > 0) { | ||
const placementsConfigsChunks = splitEvery(APPNEXUS_PLACEMENTS_PER_REQUEST_LIMIT, placementsConfig); | ||
placementsConfig.current = newPlacementConfig; | ||
if (placementsConfig.current?.length > 0) { | ||
const placementsConfigsChunks = splitEvery(APPNEXUS_PLACEMENTS_PER_REQUEST_LIMIT, placementsConfig.current); | ||
const setPlacement = (placement, placementConfig) => { | ||
placements.current = { ...placements.current, [placementConfig.targetId]: placement }; | ||
sendEvent(placementConfig.targetId, placement, placementConfig); | ||
}; | ||
placementsConfigsChunks.forEach((placementsConfigChunk) => { | ||
@@ -195,28 +195,25 @@ placementsConfigChunk.forEach((placementConfig) => { | ||
if (placementsMediation.current[placementConfig.targetId] && data.source !== 'csm') { | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: data })); | ||
setPlacement(data, placementConfig); | ||
} | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adAvailable, placementConfig.targetId, (data) => { | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: data })); | ||
setPlacement(data, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adBadRequest, placementConfig.targetId, (error) => { | ||
logger({ error, placementConfig }); | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: null })); | ||
onEvent(APPNEXUS_EVENT_TYPES.adBadRequest, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adError, placementConfig.targetId, (error) => { | ||
logger({ error, placementConfig }); | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: null })); | ||
onEvent(APPNEXUS_EVENT_TYPES.adError, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adCollapse, placementConfig.targetId, () => { | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: null })); | ||
setPlacement(null, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adNoBid, placementConfig.targetId, () => { | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: null })); | ||
setPlacement(null, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adRequestFailure, placementConfig.targetId, (error) => { | ||
logger({ error, placementConfig }); | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: null })); | ||
onEvent(APPNEXUS_EVENT_TYPES.adRequestFailure, placementConfig.targetId, () => { | ||
setPlacement(null, placementConfig); | ||
}); | ||
onEvent(APPNEXUS_EVENT_TYPES.adRequested, placementConfig.targetId, () => { | ||
setPlacements((state) => ({ ...state, [placementConfig.targetId]: undefined })); | ||
setPlacement(undefined, placementConfig); | ||
}); | ||
@@ -226,22 +223,50 @@ }); | ||
}); | ||
} | ||
}); | ||
return () => { | ||
placementsConfig.forEach((placementConfig) => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
}); | ||
}; | ||
const handleLoadAdsReload = useEvent(() => { | ||
if (retryLoadAds.current) { | ||
const params = retryLoadAds.current; | ||
retryLoadAds.current = false; | ||
loadAds(params); | ||
} | ||
}); | ||
return noop; | ||
}, [placementsConfig, adsConfig?.placements?.common]); | ||
// handles edge case when devie changes from undefined to something useful | ||
useEffect(() => { | ||
handleLoadAdsReload(); | ||
}, [device, handleLoadAdsReload]); | ||
const clearPlacements = useEvent(() => { | ||
placementsConfigRef.current?.forEach((placementConfig) => { | ||
cleanUpPlacement(placementConfig.targetId); | ||
hasClearPlacementsBeenCalledLast.current = true; | ||
placementsConfig.current.forEach((placementConfig) => { | ||
sendEvent(placementConfig.targetId, null); // null to collapse all placements | ||
}); | ||
setPlacements({}); | ||
setPlacementsConfig([]); | ||
placements.current = {}; | ||
placementsConfig.current = []; | ||
placementsMediation.current = {}; | ||
}); | ||
useEffect(() => { | ||
scriptsLoadPromise.current = Promise.all([ | ||
loadScript(cdn, 'adsScript'), | ||
loadScript(cogwheelCdn, 'cogwheelScript'), | ||
]) | ||
.then(() => { | ||
if (!isASTLoaded()) { | ||
setUpAPNObject(); | ||
} | ||
subscribeToASTLoad((ready) => { | ||
adScriptsReady.current = ready; | ||
handleLoadAdsReload(); | ||
}); | ||
resolveAdBlockerDetectedPromise(false); | ||
}) | ||
.catch(() => { | ||
resolveAdBlockerDetectedPromise(true); | ||
return null; | ||
}); | ||
}, [cdn, cogwheelCdn, handleLoadAdsReload]); | ||
const value = useMemo( | ||
@@ -251,8 +276,6 @@ () => ({ | ||
clearPlacements, | ||
placementsConfig, | ||
placements, | ||
logger, | ||
adBlockerDetectedPromise, | ||
adsEventTarget: adsEventTarget.current, | ||
}), | ||
[placementsConfig, loadAds, placements, clearPlacements, logger] | ||
[loadAds, clearPlacements] | ||
); | ||
@@ -285,3 +308,2 @@ | ||
}).isRequired, | ||
loggingEnabled: PropTypes.bool, | ||
keywords: PropTypes.shape({ | ||
@@ -288,0 +310,0 @@ common: PropTypes.shape({ |
@@ -1,2 +0,2 @@ | ||
import { useContext, useMemo } from 'react'; | ||
import { useContext, useEffect, useMemo, useState } from 'react'; | ||
import { showTag } from './utils/appnexus'; | ||
@@ -7,6 +7,25 @@ import AdContext from './AdContext'; | ||
const usePlacement = (targetId) => { | ||
const { placementsConfig, placements } = useContext(AdContext); | ||
const placementConfig = placementsConfig.find((p) => p.targetId === targetId); | ||
const placement = placements[targetId]; | ||
const { adsEventTarget } = useContext(AdContext); | ||
const [placement, setPlacement] = useState(); | ||
const [placementConfig, setPlacementConfig] = useState(); | ||
useEffect(() => { | ||
const listener = (e) => { | ||
const data = e.detail; | ||
setPlacement(data.placement); | ||
// placementConfig doesn't change so we save some computation not sending it when clearing placements | ||
if (data.placementConfig) { | ||
setPlacementConfig(data.placementConfig); | ||
} | ||
}; | ||
adsEventTarget.addEventListener(targetId, listener); | ||
adsEventTarget.dispatchEvent(new CustomEvent('resend', { detail: targetId })); | ||
return () => { | ||
adsEventTarget.removeEventListener(targetId, listener); | ||
}; | ||
}, [adsEventTarget, targetId]); | ||
const showAd = useEvent(() => { | ||
@@ -18,5 +37,5 @@ if (placement?.targetId) { | ||
return useMemo(() => [placement, showAd, placementConfig], [placement, showAd, placementConfig]); | ||
return useMemo(() => [placement, showAd, placementConfig], [placement, placementConfig, showAd]); | ||
}; | ||
export default usePlacement; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
99331
1392
219