google-publisher-tag
Version:
Type-safe React wrapper for Google Publisher Tag (GPT).
83 lines (82 loc) • 3.23 kB
JavaScript
"use client";
import { jsx as _jsx } from "react/jsx-runtime";
import { createContext, useContext, useEffect, useMemo, useRef, } from "react";
import { loadGPT } from "./loader";
const GPTContext = createContext(null);
export function GPTProvider({ children, config, }) {
const configuredRef = useRef(false);
const cfg = useMemo(() => config ?? {}, [config]);
useEffect(() => {
loadGPT().then((googletag) => {
if (configuredRef.current)
return;
configuredRef.current = true;
googletag.cmd.push(() => {
const pubads = googletag.pubads();
if (cfg.enableSingleRequest)
pubads.enableSingleRequest();
if (cfg.lazyLoad)
pubads.enableLazyLoad(cfg.lazyLoad === true ? {} : cfg.lazyLoad);
if (cfg.forceSafeFrame)
pubads.setForceSafeFrame(true);
if (cfg.requestNonPersonalizedAds != null)
pubads.setPrivacySettings({
nonPersonalizedAds: !!cfg.requestNonPersonalizedAds,
});
if (cfg.targeting) {
Object.entries(cfg.targeting).forEach(([k, v]) => pubads.setTargeting(k, v));
}
googletag.enableServices();
(cfg.slots ?? []).forEach((slotCfg) => {
defineSlotInternal(googletag, slotCfg);
});
});
});
}, [cfg]);
const defineSlot = (slotCfg) => loadGPT().then((googletag) => new Promise((resolve) => {
googletag.cmd.push(() => {
const handle = defineSlotInternal(googletag, slotCfg);
resolve(handle);
});
}));
const setTargeting = (t) => loadGPT().then((googletag) => new Promise((resolve) => {
googletag.cmd.push(() => {
const pubads = googletag.pubads();
Object.entries(t).forEach(([k, v]) => pubads.setTargeting(k, v));
resolve();
});
}));
const value = useMemo(() => ({
configured: configuredRef.current,
config: cfg,
defineSlot,
setTargeting,
}), [cfg]);
return _jsx(GPTContext.Provider, { value: value, children: children });
}
function defineSlotInternal(googletag, cfg) {
const pubads = googletag.pubads();
const slot = cfg.outOfPage
? googletag.defineOutOfPageSlot(cfg.adUnitPath, cfg.id)
: googletag.defineSlot(cfg.adUnitPath, cfg.sizes, cfg.id);
if (!slot)
return { slot: null, destroy: () => { } };
if (cfg.sizeMapping && slot.defineSizeMapping) {
const sm = googletag.sizeMapping();
cfg.sizeMapping.forEach(([vp, sizes]) => sm.addSize(vp, sizes));
slot.defineSizeMapping(sm.build());
}
slot.addService(pubads);
if (cfg.targeting)
Object.entries(cfg.targeting).forEach(([k, v]) => slot.setTargeting(k, v));
return {
slot,
destroy: () => googletag.destroySlots([slot]),
};
}
export function useGPT() {
const ctx = useContext(GPTContext);
if (!ctx)
throw new Error("useGPT deve ser usado dentro de <GPTProvider />");
return ctx;
}