如何在NuxtJs3/VueJs3中正确部署Google Ads Manager横幅广告单元
部署Google Ads Manager广告单元到Nuxt3/Vue3项目(SSR/SPA兼容)
问题背景
现有Google Ads Manager广告单元代码如下:
<script type="text/javascript"> google_ad_client = "ca-pub-2158343444694791";/* AD7 */ google_ad_slot = "AD7"; google_ad_width = 300; google_ad_height = 250; </script> <script type="text/javascript" src="//pagead2.googlesyndication.com/pagead/show_ads.js"></script>
项目基于Nuxt3/Vue3开发,支持SSR和SPA模式,需在首页5个不同位置展示该横幅广告,但无法直接在Vue模板中放置script标签。
尝试过的方案
模板代码
<div class="my_div"></div>
JavaScript代码
nuxt.hook("page:loading:end", () => { loaderLoading.value = false setTimeout(() => { var div = document.querySelector('.my_div'); // Create a script element var script = document.createElement('script'); // Set the type attribute script.type = 'text/javascript'; // Set the source (src) attribute script.src = '//pagead2.googlesyndication.com/pagead/show_ads.js'; // Create an inline script element for the ad parameters var inlineScript = document.createElement('script'); inlineScript.type = 'text/javascript'; inlineScript.innerHTML = ` google_ad_client = "ca-pub-2158343444694791"; /* AD7 */ google_ad_slot = "AD7"; google_ad_width = 300; google_ad_height = 250; `; console.log("test") // Append the inline script to the div div.appendChild(inlineScript); // Append the script to the div div.appendChild(script); }, 2000); })
遇到的错误
Uncaught TagError: adsbygoogle.push() error: Ad client is missing from the slot. Uncaught TypeError: Cannot read properties of null (reading 'appendChild') Unchecked runtime.lastError: The message port closed before a response was received.
解决方案
错误原因解析
- DOM元素找不到:
document.querySelector('.my_div')仅能获取第一个匹配元素,且page:loading:end钩子触发时,客户端DOM可能尚未完全渲染,导致返回null。 - 广告参数作用域/时机问题:动态创建的内联脚本执行时机晚于广告脚本加载,导致Google广告脚本无法读取全局的
google_ad_client等参数。 - 重复加载脚本:未做脚本加载判断,多次执行会重复插入广告脚本,引发冲突。
正确实现步骤
1. 模板层:为每个广告位置设置唯一标识
<template> <ClientOnly> <!-- 首页5个独立广告位置,使用唯一ID区分 --> <div class="ad-slot" id="ad-slot-1"></div> <div class="ad-slot" id="ad-slot-2"></div> <div class="ad-slot" id="ad-slot-3"></div> <div class="ad-slot" id="ad-slot-4"></div> <div class="ad-slot" id="ad-slot-5"></div> </ClientOnly> </template>
使用
ClientOnly组件确保广告容器仅在客户端渲染,避免SSR时出现DOM相关错误。
2. 封装广告加载逻辑(组合式函数)
创建composables/useGAMAd.js,复用广告加载逻辑并避免重复请求:
export const useGAMAd = () => { // 标记脚本是否已加载 let scriptLoaded = false; // 加载广告基础脚本 const loadAdBaseScript = () => { if (scriptLoaded) return; // 全局设置广告客户端ID window.google_ad_client = "ca-pub-2158343444694791"; const script = document.createElement('script'); script.type = 'text/javascript'; script.src = '//pagead2.googlesyndication.com/pagead/show_ads.js'; script.async = true; script.onload = () => scriptLoaded = true; document.body.appendChild(script); }; // 渲染单个广告位 const renderAdSlot = (slotId, adSlot = "AD7", width = 300, height = 250) => { const slotEl = document.getElementById(slotId); if (!slotEl) return; // 为当前广告位设置参数 window.google_ad_slot = adSlot; window.google_ad_width = width; window.google_ad_height = height; // 创建内联脚本触发广告渲染 const inlineScript = document.createElement('script'); inlineScript.type = 'text/javascript'; inlineScript.textContent = ` (function() { window.google_ad_slot = "${adSlot}"; window.google_ad_width = ${width}; window.google_ad_height = ${height}; })(); `; slotEl.appendChild(inlineScript); // 确保基础脚本已加载 loadAdBaseScript(); }; return { renderAdSlot }; };
3. 首页组件中调用渲染逻辑
在首页组件的onMounted钩子中执行广告渲染(仅客户端执行):
<script setup> import { onMounted } from 'vue'; import { useGAMAd } from '@/composables/useGAMAd'; const { renderAdSlot } = useGAMAd(); onMounted(() => { // 延迟短时间确保DOM完全渲染 setTimeout(() => { // 依次渲染5个广告位,若使用不同广告单元可修改adSlot参数 renderAdSlot('ad-slot-1'); renderAdSlot('ad-slot-2'); renderAdSlot('ad-slot-3'); renderAdSlot('ad-slot-4'); renderAdSlot('ad-slot-5'); }, 500); }); </script>
关于Google Ads Manager支持库
目前没有官方针对Nuxt3/Vue3的GAM集成库,推荐通过手动封装组合式函数实现逻辑复用。若需复杂广告管理(如响应式广告、广告刷新),可直接调用GAM原生API,确保所有代码在客户端环境执行即可。
关键注意事项
- 所有广告相关代码必须在客户端执行,避免SSR时出现
document未定义错误。 - 广告基础脚本仅加载一次,避免重复请求和冲突。
- 每个广告位使用唯一ID,确保能精准定位DOM元素。
- 若使用多个不同广告单元,需为每个广告位传入对应的
adSlot参数。 - 延迟执行时间可根据页面渲染速度调整,无需设置过长(500ms左右足够)。
内容的提问来源于stack exchange,提问作者aboal7roof Masri
相关产品推荐
相关产品推荐

