Nuxt:在插件内部,如何将动态脚本标签添加到头部?

Dre*_*ker 5 head vue.js nuxt.js gtag.js

我正在尝试为 Nuxt 构建一个 Google Analytics 插件,该插件将从 CMS 获取跟踪 ID。我想我真的很接近。

我有一个仅在客户端加载的插件文件。nuxt.config.js该插件是通过数组加载的plugins:[{ src: '~/plugins/google-gtag.js', mode: 'client' }]

从那里开始,主要问题是 gtag 脚本需要其 URL 中的 UA 代码,因此我不能将其添加到nuxt.config.js. 我需要从商店获取这些 UA 代码(它是水合形式的nuxtServerInit.

因此,我head.script.push在插件中使用 URL 中的 UA 代码添加 gtag 脚本。但这不会导致在第一页加载时添加脚本,但会在所有后续页面转换中添加脚本。很明显,我head.script.push在页面渲染中运行得太晚了。

但我不知道如何获取跟踪 ID,然后将脚本添加到头部。

// plugins/google.gtag.client.js with "mode": "client
export default ({ store, app: { head, router, context } }, inject) => {
    // Remove any empty tracking codes
    const codes = store.state.siteMeta.gaTrackingCodes.filter(Boolean)

    // Add script tag to head
    head.script.push({
        src: `https://www.googletagmanager.com/gtag/js?id=${codes[0]}`,
        async: true
    })
    console.log('added script')

    // Include Google gtag code and inject it (so this.$gtag works in pages/components)
    window.dataLayer = window.dataLayer || []
    function gtag() {
        dataLayer.push(arguments)
    }
    inject('gtag', gtag)
    gtag('js', new Date())

    // Add tracking codes from Vuex store
    codes.forEach(code => {
        gtag('config', code, {
            send_page_view: false // necessary to avoid duplicated page track on first page load
        })

        console.log('installed code', code)

        // After each router transition, log page event to Google for each code
        router.afterEach(to => {
            gtag('event', 'page_view', { page_path: to.fullPath })
            console.log('afterEach', code)
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

Dre*_*ker 7

我最终让它发挥作用,我们在生产中使用它。

截至撰写本文时,代码如下所示:

export default ({ store, app: { router, context } }, inject) => {
    // Remove any empty tracking codes
    let codes = _get(store, "state.siteMeta.gaTrackingCodes", [])
    codes = codes.filter(Boolean)

    // Abort if no codes
    if (!codes.length) {
        if (context.isDev) console.log("No Google Anlaytics tracking codes set")
        inject("gtag", () => {})
        return
    }

    // Abort if in Dev mode, but inject dummy functions so $gtag events don't throw errors
    if (context.isDev) {
        console.log("No Google Anlaytics tracking becuase your are in Dev mode")
        inject("gtag", () => {})
        return
    }

    // Abort if we already added script to head
    let gtagScript = document.getElementById("gtag")
    if (gtagScript) {
        return
    }

    // Add script tag to head
    let script = document.createElement("script")
    script.async = true
    script.id = "gtag"
    script.src = "//www.googletagmanager.com/gtag/js"
    document.head.appendChild(script)

    // Include Google gtag code and inject it (so this.$gtag works in pages/components)
    window.dataLayer = window.dataLayer || []
    function gtag() {
        dataLayer.push(arguments)
    }
    inject("gtag", gtag)
    gtag("js", new Date())

    // Add tracking codes from Vuex store
    codes.forEach(code => {
        gtag("config", code, {
            send_page_view: false // Necessary to avoid duplicated page track on first page load
        })

        // After each router transition, log page event to Google for each code
        router.afterEach(to => {
            gtag("event", code, { page_path: to.fullPath })
        })
    })
}
Run Code Online (Sandbox Code Playgroud)

如果不在插件中,这是有关如何加载第 3 方脚本的好读物:如何在 Nuxt.js 中加载第三方脚本

  • 路由器转换应该是`event`而不是`config`:`gtag("event", "page_view", { page_path: to.fullPath })`。 (2认同)