Есть ли способ узнать, когда закрывается реклама Google (GPT)?Javascript

Форум по Javascript
Ответить
Anonymous
 Есть ли способ узнать, когда закрывается реклама Google (GPT)?

Сообщение Anonymous »

Итак, у меня есть рекламная палочка внизу страницы. У него есть закрытый значок, когда я нажимаю на него, мне нужно понять, есть ли способ узнать, когда объявление закрыто?

Код: Выделить всё

'use client';

import { memo, useEffect } from 'react';

export interface StickyBannerState {
height: number;
present: boolean;
slotID: string;
}

/**
* dispatchUpdate
*
* @param detail - sticky banner state
*/
const dispatchUpdate = (detail: StickyBannerState): void => {
window.dispatchEvent(
new CustomEvent('stickyBanner:update', { detail }),
);
};

interface IAdStickyBridgeProps {
slotID: string;
enabled: boolean;
}

/**
* AdStickyBridge
*
* Observes the ad slot element and emits sticky height changes.
* Also listens for a "close" postMessage from the slot's iframe.
*
* Does not call GPT APIs.  Safe alongside AdSlotClient.
*
* @param props - component props
* @param props.slotID - ad slot element id
* @param props.enabled - whether to enable observers
*/
function AdStickyBridge({
enabled,
slotID,
}: IAdStickyBridgeProps): React.ReactElement | null {
useEffect(() => {
if (!enabled || !slotID) {
return;
}

let resizeObs: ResizeObserver | null = null;
let mutationObs: MutationObserver | null = null;
let lastHeight = -1;
let lastPresent = false;

/**
* measureAndDispatch
*
* Measures the slot element and dispatches sticky state
* only when values actually change.
*/
const measureAndDispatch = (): void => {
const el = document.getElementById(slotID);

if (!el) {
if (lastHeight !== 0 || lastPresent !== false) {
lastHeight = 0;
lastPresent = false;

dispatchUpdate({ height: 0, present: false, slotID });
}

return;
}

const displayNone = Boolean(getComputedStyle(el)?.display === 'none');

const h = displayNone ? 0 : Math.max(0, el.offsetHeight || 0);
const present = h > 0;

if (h !== lastHeight || present !== lastPresent) {
lastHeight = h;
lastPresent = present;

dispatchUpdate({ height: present ? h : 0, present, slotID });
}
};

/**
* onMessage
*
* Handles postMessage coming from the slot iframe.
* Expected payloads:
* { type: 'ad-closed', slotId: '' }
* { event: 'ad-closed', slotId: '' }
*
* @param ev - message event
*/
const onMessage = (ev: MessageEvent): void => {
// 1) Soft check payload shape
const data = ev?.data as
| { type?: string; event?: string; slotId?: string }
| undefined;

if (!data) {
return;
}

console.log('marcelo data', data);

const isClose = data.type === 'ad-closed' || data.event === 'ad-closed';

if (!isClose) {
return;
}

// 2) Scope to the correct slot:
//     - If slotId is provided, require it to match.
if (data.slotId && data.slotId !== slotID) {
return;
}

// 3) Optional: verify the message comes from the slot's descendant iframe
//    (prevents unrelated messages from other frames).
const el = document.getElementById(slotID);
if (!el) {
return;
}

const frames = el.getElementsByTagName('iframe');
let fromOurFrame = false;

for (let i = 0; i < frames.length; i += 1) {
if (frames?.[i]?.contentWindow === ev.source) {
fromOurFrame = true;
break;
}
}

if (!fromOurFrame) {
return;
}

// 4) Close instruction accepted → drop sticky offset
dispatchUpdate({ height: 0, present: false, slotID });
};

// Initial measure after layout settles
requestAnimationFrame(measureAndDispatch);

// Resize observation
const el = document.getElementById(slotID);
if (el && 'ResizeObserver' in window) {
resizeObs = new ResizeObserver(() => {
measureAndDispatch();
});
resizeObs.observe(el);
}

// Watch the slot's parent (or body) for DOM/class/style changes
const parent = el?.parentNode || document.body;

mutationObs = new MutationObserver(() => {
measureAndDispatch();
});

mutationObs.observe(parent, {
attributeFilter: ['style', 'class'],
attributes: true,
childList: true,
subtree: true,
});

window.addEventListener('message', onMessage);

return (): void =>  {
if (resizeObs) {
resizeObs.disconnect();
}

if (mutationObs) {
mutationObs.disconnect();
}

window.removeEventListener('message', onMessage);

// Ensure wrapper returns to bottom on unmount
dispatchUpdate({ height: 0, present: false, slotID });
};
}, [slotID, enabled]);

return null;
}

export default memo(AdStickyBridge);

'use client';

import { memo, useEffect, useRef } from 'react';

import {
defineSlot,
getSlotById,
} from '@tu/utilities/helpers/ads/gpt/gptManager';
import type { IAdSettings } from '@tu/commons/ads/IAdSettings';
import useStore from '@tu/commons/store/Store';

import AdStickyBridge from './AdStickyBridge';

interface IAdSlotProps {
adSettings: IAdSettings | null;
lazyLoaded?: boolean;
}

/**
* AdSlotClient
*
* @param props - component props
* @param props.adSettings - ad settings
* @param props.lazyLoaded - lazy loaded
*/
function AdSlotClient({
adSettings,
lazyLoaded,
}: IAdSlotProps): React.ReactElement | null {
const hasLoad = useRef(false);
const gptStarted = useStore((state) => !!state.scriptLoaded?.gptStarted);
const hasOneTrust = useStore((state) => !!state.featureFlag?.hasOneTrust);

useEffect(() => {
let slot: googletag.Slot | undefined | null;

if (!hasLoad.current && gptStarted && adSettings) {
window.googletag = window.googletag || { cmd: [] };

window.googletag.cmd.push(() => {
if (!lazyLoaded) {
const checkSlot = getSlotById(adSettings?.slotID);

if (!checkSlot) {
slot = defineSlot(adSettings, true, hasOneTrust);
}
}

if (lazyLoaded) {
slot = getSlotById(adSettings?.slotID);

if (slot && document.getElementById(adSettings?.slotID)) {
window.googletag.pubads().refresh([slot]);
}
}
});

hasLoad.current = true;
}

return (): void => {
slot = null;
};
}, [adSettings, hasOneTrust, lazyLoaded, gptStarted]);

if (!adSettings || lazyLoaded) {
return null;
}

const isStickyCandidate =
adSettings.position === 'ADH' ||
adSettings.slotID.startsWith('div-gpt-ad-adh-');

return (




);
}

export default memo(AdSlotClient);
< /code>
Но когда я его закрываю, ничто иное не возвращается.  const [stickyBanner, setStickyBanner] = useState({
height: 0,
present: false,
slotID: '',
});

useEffect(() => {
/**
* onUpdate
*
* @param ev - event
*/
const onUpdate = (ev: Event): void => {
const e = ev as CustomEvent;

console.log('marcelo e', e);

if (!e.detail) {
return;
}

setStickyBanner(e.detail);
};

window.addEventListener('stickyBanner:update', onUpdate as EventListener);

return (): void =>
window.removeEventListener(
'stickyBanner:update',
onUpdate as EventListener,
);
}, [nodeId]);
Когда компонент устанавливается, kickybanner.present и kickybanner.height - фальсификация, после секунды они становятся правдой, и когда я закрываю рекламу, ничто иное не изменится обратно на фальсификацию.
>

Подробнее здесь: https://stackoverflow.com/questions/797 ... ing-closed
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Javascript»