NextJS:在路线更改时重新加载广告 Javascript 和广告位

asa*_*nas 19 javascript next.js

我有一个自定义 JavaScript,用于在我的 NextJS 网站上运行广告。这是由广告提供商/广告交易平台提供的。

它看起来像这样:

<script type="text/javascript" src="//cdn.adsite.com/static/js/ad.js" ></script>
Run Code Online (Sandbox Code Playgroud)

除此之外,我还在网页上放置了 div 标签,例如:

<div id="ad-tag-6098" ></div>
<div id="ad-tag-6099" ></div>
<div id="ad-tag-6076" ></div>
Run Code Online (Sandbox Code Playgroud)

这三个 div 标签是页面上的三个广告位,并使用 ad.js javascript 填充广告。

这对于页面的正常加载/重新加载效果很好。

但是,当我使用内部导航路由器导航到页面时,不会触发此 JavaScript,并且不会显示广告。

重新加载 ad.js 以便 div 标签(广告位)正确显示广告,并且即使我们通过 nextjs 路由器导航也能正确刷新的正确方法是什么?你能帮忙吗?

更新:这个问题比我想象的还要深。仅仅重新加载 javascript 是不够的。由于这些是广告位,当页面转换/路线改变时,使用的广告位保留在内存中,因此广告脚本将它们视为已经显示。这会导致错误。

期望的行为如下:

  1. 当广告组件呈现时,它定义广告位并显示它,
  2. 当路由改变时,所有定义的槽都会从内存中删除,
  3. 进入不同页面后,该页面上的广告组件会定义新的广告位并显示它们。

oak*_*kar 7

你可能知道,但我想提醒你,NextJS 中有路由更改的监听器

  router.events.on('routeChangeComplete', handleRouteChange)
  router.events.off('routeChangeComplete', handleRouteChange)
Run Code Online (Sandbox Code Playgroud)

当路线发生变化时,您可以借助这些事件重新加载脚本。您可以获取脚本并将其附加到每次路由更改的正文脚本的末尾。所以adjs的内存将被重新启动

我希望这个 router.events 对您有所帮助,等待您的反馈。

更新: 根据您的评论,我想在这里更新。在这些 router.events 的帮助下,您可以进行控制。您可以操作 DOM。它不应该是 React 特定解决方案或 NextJS 特定解决方案。你拥有 JavaScript 的力量。

如果您是添加所有广告 div 的人,则可以添加数据属性以稍后选择这些 div。

例如,假设您添加了此广告 div

<div id="ad-tag-6098" ></div> // instead of this!
<div id="ad-tag-6098" data-ad="true" ></div> // add this one!
Run Code Online (Sandbox Code Playgroud)

通过使用router.events的routeChangeStart事件,您可以选择具有data-ad属性的div,并在routeChangeComplete事件之前从DOM中删除它们的填充内容,并且当重新加载脚本时,它不应该抛出错误。

const adDivs = document.querySelectorAll('[data-ad="true"]'); // you can get these divs and remove the child of them before routeChangeComplete cycle
Run Code Online (Sandbox Code Playgroud)

您对我的答案的更新部分有何看法,请告诉我您的想法。

  • 我能够部分实施这个解决方案。使用 useEffect 挂钩,当路线更改时,我可以重新加载脚本。但是,像 &lt;div id="ad-tag-6098"&gt;&lt;/div&gt; 这样的广告位已经预先填充了广告。并且脚本会抛出广告已填充的错误。因此,需要删除并重新创建这些广告位,以使广告能够正常运行。请参阅我的问题的最后部分以及预期的行为。 (3认同)

Cha*_*dan 6

另一个简单的技巧是添加唯一的查询字符串,这将导致脚本一次又一次地加载和执行。

为了删除旧ads Script组件,onLoad可以使用事件处理程序。

import Script from 'next/script'

export default function Home() {
  const unique_id = new Date().getTime();
  return (
    <>
      <Script
        id={unique_id}
        src={`//cdn.adsite.com/static/js/ad.js?v=${unique_id}`}
        onLoad={() => {
          // execute code after script load
        }}
      />
    </>
  )
}
Run Code Online (Sandbox Code Playgroud)

更好的方法是仅加载脚本一次并刷新使用提供的刷新功能创建的广告位,或者您可以清除并加载具有相同功能的新广告。

function refreshAllSlots() {
   googletag.cmd.push(function() {
     googletag.pubads().refresh();
   });
}

function clearAllSlots() {
  googletag.cmd.push(function() {
    googletag.pubads().clear();
  });
}
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 该示例适用于谷歌广告,但在其他广告中可能也可以实现相同的效果。
  • 可以使用生命周期方法或钩子或任何其他可行的方法来调用这些方法。