没事造轮子没事造轮子

没事造轮子

Google Analytics 和 Adsense

  • W_Z_C
  • 阅读约 3 分钟
Google Analytics 和 Adsense

本篇文章主要讲解如何在 Nextjs 搭建的网站中添加 Google 统计以及如何设置 Google Adsense。因为 Nextjs 的前端在点击链接的时候并不会刷新当前页面,所以你需要对添加的代码做一些特别的处理,下面详细介绍一下。

1. Nextjs 中添加 Google Analytics 代码

首先你需要在现有工程文件的环境变量中加入你的跟踪代码,这个代码是 Google Analytics 自动分配的,一般以 ga-pub- 开头:

NEXT_PUBLIC_GOOGLE_ADSENSE=ca-pub-4519964266657944

目前我直接将其放到 .env 文件中,这样在开发的过程中,该环境变量会自动加载。接下来将 Google Analytics 的官方提供的脚本注入到前端页面中。

_app.js
import * as ga from '../libs/ga'

function App({ Component, pageProps }) {

  useEffect(() => {
    //...

    const handleChangeComplete = (url) => {
      setLoading(false)
      ga.pageview(url)
    }

    //...
  }, [router])

  return (
    <>
      <DefaultSeo {...DefSEO} />

      //...

      <Head>
        <Script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}`} />
        <Script id='mszlz_gtag' 
          dangerouslySetInnerHTML={{
            __html: `
                    window.dataLayer = window.dataLayer || [];
                    function gtag(){dataLayer.push(arguments);}
                    gtag('js', new Date());

                    gtag('config', '${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}', {page_path: window.location.pathname});
                `
          }}
        />
      </Head>

      <Loading loading={loading} />
      
      //...
    </>
  )
}

export default App

这里面导入了一个 ga 文件,该文件的内容主要是调用 Google Analytics 提供的结构,记录访问过的网页链接:

ga/index.js
export const pageview = (url) => {
    window.gtag('config', process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS, {
        page_path: url,
    })
}

除此之外,你还可以使用 window.gtag 来记录特殊事件,具体可以参考 Google Analytics 的官方文档。

2. Nextjs 中添加 Google Adsense 代码

与添加 Google Analytics 类似的是添加 Google Adsense 代码,不过 Google 对 Adsense 的代码监控的比较严,主要是防止你进行作弊。为了添加方便,我定义了一个 Ads 组件:

GoogleAds.js
import React, { useEffect } from "react"

const adUnitProps = {
    CUBE: {
        'data-ad-slot': 'xxx',
        'data-ad-format': "xxx",
        'data-full-width-responsive': "xxx",
    },

    VERTICAL: {
        'data-ad-slot': "xxx",
        'data-ad-format': "xxx",
        'data-full-width-responsive': "xxx",
    }
}


export function GoogleAds({ type, currentPath }) {

    useEffect(() => {
        try {
            window.adsbygoogle = window.adsbygoogle || []
            window.adsbygoogle.push({})
        } catch(e) {
            console.error(e)
        }
    }, [currentPath])

    return (
        <div key={currentPath} aria-hidden={true} className="overflow-hidden max-w-5xl mx-auto mb-8">
            <ins className="adsbygoogle block"
                data-ad-client={process.env.NEXT_PUBLIC_GOOGLE_ADSENSE}
                {...adUnitProps[type]}
            >
            </ins>
        </div>
    )
}

你有几种广告类型,你就定义几类数据,每个广告里面等属性是摘自 Google Adsense 后台自建广告的代码片段,这样当你想要显示广告的时候,只需要使用下面的代码片段即可:

<GoogleAds
    type={'VERTICAL'}
    currentPath={meta.slug}
/>

对了,在使用之前不要忘记添加 Google Adsense 的官方脚本,否则代码是不会生效的:

_app.js

function App({ Component, pageProps }) {return (  <>    //...
    <Head>       <Script async src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${process.env.NEXT_PUBLIC_GOOGLE_ADSENSE}`} crossOrigin="anonymous" />      <Script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}`} />      <Script id='mszlz_gtag'         dangerouslySetInnerHTML={{          __html: `							window.dataLayer = window.dataLayer || [];							function gtag(){dataLayer.push(arguments);}							gtag('js', new Date());
							gtag('config', '${process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS}', {page_path: window.location.pathname});						`        }}      />    </Head>      //...  </>)}

如果你和我一样使用的是最新的 React18 以上的版本,那么可能会遇见第一个蛋疼的错误:

adsbygoogle.push() error: All ins elements in the DOM with class=adsbygoogle already have ads in them.

Adsense 脚本会抱怨你调用了它两次,造成这个原因主要是 React 更新了它的严格模式策略,你可以在 Next dev with React 18, Always render twice 查看相关的讨论情况。

这个问题只会发生在开发模式下,你测试的时候可以尝试关闭严格模式:

next.config.js
const nextConfig = {
  reactStrictMode: false,
}

也可以通过环境变量区分,当开发模式的情况做一些特殊处理即可。除此之外,你还可能另一个蛋疼的错误:

adsbygoogle.push() error: No slot size for availableWidth=0 when i use responsive ads

这个错误主要是因为 Google 在现实广告的时候没有检测到可以显示的宽度信息,这里面原因有很多种,大多数是因为显示广告的时候文档没有加载完成,所以导致 Google 的广告脚本检测不到父节点的宽度。解决这个问题需要用到我在前面提到的 loading 状态,不知道你还记得不,这个状态变量是在显示加载动画的时候引进的,loading 为 false 表示加载完成,借助这个信息,在现实广告的时候可以增加一个条件变量:

(!loading) && (<GoogleAds
    type={'VERTICAL'}
    currentPath={meta.slug}
/>)

搞定之后,应该就不会再次出现其它错误了。