Nuxt Composition Api项目中GPT Ads页面切换失效及报错解决
问题:Nuxt中使用Composition API集成GPT广告切换页面后失效并报错
在Nuxt项目中使用Composition API集成Google Publisher Tags(GPT)广告服务,首次加载页面时广告运行正常,但切换页面后广告区域消失,同时出现以下报错:
报错信息
- Error in googletag.defineSlot: Cannot create slot /1347001/main-masthead. Div element "div-gpt-ad-1559997122392-0" is already associated with another slot: /1347001/main-masthead.
- pubads_impl_2022092701.js?cb=31069995:18: Exception in queued GPT command TypeError: Cannot read properties of null (reading 'addService')
相关代码
ads.js
export const adIntegration = () => { const adScript = document.createElement('script'); adScript.type = 'text/javascript'; adScript.src = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js'; document.head.appendChild(adScript); }; export const mainPageAd = ({ path, size, id }) => { adIntegration(); window.googletag = window.googletag || { cmd: [] }; googletag.cmd.push(() => { googletag.defineSlot(path, size, id).addService(googletag.pubads()); googletag.pubads().enableSingleRequest(); googletag.enableServices(); googletag.display(id); }); };
index.vue
<template lang="pug"> .home-page .advertisement( :id="adSlot.id" style='min-width: 955px; min-height: 240px') <script> import { mainPageAd } from '~/common/utils/ads'; setup(){ const adSlot = ref({ path: '/21737763597/adunit-1', size: [320, 100], id: 'div-gpt-ad-1559997122392-0', }); onMounted(() => { mainPageAd({ path: adSlot.value.path, size: adSlot.value.size, id: adSlot.value.id }); } return{adSlot} </script>
解决方案
问题根源
- 页面切换时重复调用广告初始化函数,导致同一个DOM元素被绑定多个GPT slot,违反GPT的唯一性规则。
- 重复插入GPT脚本,引发脚本加载状态混乱,出现
addService读取null的错误。 - 组件卸载时未清理GPT的slot资源,残留的slot与新创建的slot冲突。
1. 确保GPT脚本仅加载一次
修改adIntegration函数,检查脚本是否已存在,避免重复插入:
export const adIntegration = () => { // 检查GPT脚本是否已加载 if (document.querySelector('script[src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"]')) { return; } const adScript = document.createElement('script'); adScript.type = 'text/javascript'; adScript.src = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js'; document.head.appendChild(adScript); };
2. 避免重复定义slot,新增资源清理函数
修改ads.js,添加slot存在性检查,同时新增组件卸载时的清理逻辑:
export const adIntegration = () => { if (document.querySelector('script[src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"]')) { return; } const adScript = document.createElement('script'); adScript.type = 'text/javascript'; adScript.src = 'https://securepubads.g.doubleclick.net/tag/js/gpt.js'; document.head.appendChild(adScript); }; export const mainPageAd = ({ path, size, id }) => { adIntegration(); window.googletag = window.googletag || { cmd: [] }; googletag.cmd.push(() => { // 检查是否已存在对应ID的slot const existingSlot = googletag.pubads().getSlots().find(slot => slot.getSlotElementId() === id); if (existingSlot) { // 已存在则直接显示 googletag.display(id); return; } // 不存在则创建新slot googletag.defineSlot(path, size, id).addService(googletag.pubads()); googletag.pubads().enableSingleRequest(); googletag.enableServices(); googletag.display(id); }); }; // 新增:组件卸载时清理对应slot export const destroyAd = (id) => { window.googletag = window.googletag || { cmd: [] }; googletag.cmd.push(() => { const targetSlot = googletag.pubads().getSlots().find(s => s.getSlotElementId() === id); if (targetSlot) { googletag.destroySlots([targetSlot]); } }); };
3. 在组件中添加卸载钩子
修改index.vue的setup函数,调用清理函数释放资源:
<template lang="pug"> .home-page .advertisement( :id="adSlot.id" style='min-width: 955px; min-height: 240px') <script> import { ref, onMounted, onUnmounted } from 'vue'; import { mainPageAd, destroyAd } from '~/common/utils/ads'; export default { setup(){ const adSlot = ref({ path: '/21737763597/adunit-1', size: [320, 100], id: 'div-gpt-ad-1559997122392-0', }); onMounted(() => { mainPageAd({ path: adSlot.value.path, size: adSlot.value.size, id: adSlot.value.id }); }); // 组件卸载时清理广告slot onUnmounted(() => { destroyAd(adSlot.value.id); }); return { adSlot } } } </script>
内容的提问来源于stack exchange,提问作者oktay tontaş
相关产品推荐
相关产品推荐

