Next.js: Добавляете тег скрипта GA?

Созданный на 30 окт. 2016  ·  74Комментарии  ·  Источник: vercel/next.js

Всем привет!

В настоящее время я конвертирую свой веб-сайт в проект next.js и не могу понять, как добавить на страницу тег скрипта Google Analytics. Есть предположения?

Привет,
Робин

Самый полезный комментарий

Нет необходимости в react-ga . Используйте диспетчер тегов Google с компонентом <Head> для добавления аналитики. В код менеджера тегов Google внесены небольшие изменения, чтобы он работал в nextjs / response:

<Head>
      <script dangerouslySetInnerHTML={{__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-XXXXXX');`}} />
    </Head>
    <noscript dangerouslySetInnerHTML={{__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX" height="0" width="0" style="display:none;visibility:hidden;"></iframe>`}} />

image

Все 74 Комментарий

оформить заказ <Head>

@robinvdvleuten Я бы предложил создать компонент GoogleTagManager и включить его в Head или сразу после него, в зависимости от вашего выбора реализации.

как уже упоминалось, вы можете использовать тег Head или удобное для реакции решение, например https://github.com/react-ga/react-ga

Есть какие-нибудь советы, как заставить react -ga работать с next.js?

@gtramontina должно работать. В противном случае я один из участников react-ga так что я мог бы помочь с этим

Нет необходимости в react-ga . Используйте диспетчер тегов Google с компонентом <Head> для добавления аналитики. В код менеджера тегов Google внесены небольшие изменения, чтобы он работал в nextjs / response:

<Head>
      <script dangerouslySetInnerHTML={{__html: `(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
        new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
        j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
        'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
      })(window,document,'script','dataLayer','GTM-XXXXXX');`}} />
    </Head>
    <noscript dangerouslySetInnerHTML={{__html: `<iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX" height="0" width="0" style="display:none;visibility:hidden;"></iframe>`}} />

image

Я бы порекомендовал лучшее решение для отслеживания просмотра страницы на стороне клиента: autotrack. См. Https://github.com/MoOx/phenomic/issues/384 для получения дополнительной информации.

@impronunciable было бы здорово иметь пример, так как после некоторого поиска в Google я все еще в замешательстве 😃 Можно ли открыть его снова?

  • @MoOx, похоже, подразумевает, что Google AutoTrack
  • но Autotrack инструктирует создать тег скрипта с кодом, который обращается к объекту window , так что это не работает на стороне сервера
  • и в любом случае, если вы используете компонент React, такой как react-ga, где его следует разместить? В render ? componentWillMount ? getInitialProps ? Это не очень ясно, поскольку предполагается, что вы используете реактивный маршрутизатор и загружаете код один раз для всех страниц.

Отслеживание страницы должно работать как при рендеринге страницы на сервере, так и при переходе на другую страницу. Было бы здорово увидеть, как все это должно интегрироваться в типичное приложение Next с заголовком, HOC макета страницы и т. Д.

Также было бы здорово узнать, считаете ли вы, что есть лучшая / более простая / менее громоздкая / современная комбинация, чем Next.js + Google Analytics Autotrack ...

Я могу исследовать это

Во вторник, 17 января 2017 г., 7:59 Себастьен Дюбуа [email protected]
написал:

@impronunciable https://github.com/impronunciable, было бы здорово
есть пример, так как после некоторого поиска в Google я все еще в замешательстве 😃 Может ли это
быть вновь открытыми?

  • @MoOx https://github.com/MoOx, похоже, подразумевает, что response -ga не
    необходимо, следует использовать Google AutoTrack
    https://github.com/googleanalytics/autotrack вместо этого
  • но Autotrack инструктирует создать тег скрипта с кодом, который
    обращается к объекту окна, поэтому он не работает на стороне сервера
  • и в любом случае, если вы используете компонент реакции, такой как react-ga, где следует
    это поставить? В рендере? componentWillMount? getInitialProps? Это не
    супер ясно, поскольку это предполагает, что вы используете реактивный маршрутизатор и загружаете
    кодируйте один раз для всех страниц.

Отслеживание страницы должно работать как когда страница отображается на сервере, так и
затем при переходе на другую страницу. Было бы здорово увидеть, как
все это должно быть интегрировано в типичное приложение Next с заголовком, страницей
макет HOC и др.

Также было бы здорово узнать, думаете ли вы, что есть лучше / проще / меньше
громоздкая / более современная комбинация, чем Next.js + Google
Автоматическое отслеживание аналитики ...

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-273108099 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AAKHp9-2bfLXj2hMGlNlkqUSRqEL7R2Cks5rTJ8kgaJpZM4KkXxa
.

Совершенно уверен, что автоматического отслеживания более чем достаточно, он вводится только на стороне клиента - не нужно думать о стороне сервера.

См. Https://github.com/MoOx/react-toulouse/commit/c42045d1001ab813c5d7eae5ab2f4f8c08c0025e в качестве примера. Он не используется дальше, но я думаю, его будет легко адаптировать.

Да, мы не хотим отслеживать рендеринг сервера, так как он запутывает такие вещи, как местоположение.

Нет, так как это будет обрабатывать клиент: имейте в виду, что страница запрашивается клиентом и будет отображаться в браузере клиента :)

Хорошо, я не понимал, что код не должен работать на стороне сервера. Итак, я использовал автодорожку , как рекомендовано https://github.com/relatenow/relate/commit/50dc3f317eb3efa045d5bbe40d1a1a1ad1116458

Просто еще не подтвердил, правильно ли он считает просмотры страниц, для меня это в новинку 😬 😄

Вы можете использовать представление «в реальном времени» для легкой отладки GA.

@MoOx да ну вот что меня беспокоит, я ничего не вижу в панели реального времени, когда захожу на https://relate.now.sh параллельно на другой вкладке (0 активных пользователей)

Я все еще не понимаю ... Я не получаю никаких данных с написанным мной кодом.

Все примеры, которые я вижу, похоже, требуют <script href="https://www.google-analytics.com/analytics.js" async /> но что-то в Head, похоже, не выполняется в клиенте? (мой console.log не печатается в консоли браузера ...)

Будем очень признательны за пример 🙂

Ах, он заработал, переключившись на response-ga 😄

https://github.com/relatenow/relate/commit/a9d2bce46e5314075af7c12bbaa0266865ff25da

screen shot 2017-01-18 at 14 01 28

Как ты заставил это работать? Я пытался вызвать функцию просмотра страницы на componentDidMount .

Сбой проверки рабочего приложения

@luandro не помнит подробностей, но вы можете посмотреть коммит, который я указал выше, если это поможет

Я сделал и попробовал. Я сделал то же самое, что и вы, вызвав configureAnalytics сверху и просмотрев страницу на componentWillMount , но все равно получил отрицательный результат на GA Check .

В вашем коде не похоже, что вы на самом деле подключили страницу где-нибудь, не так ли?

@luandro Просто добавьте ga(‘set’, ‘page’, window.location.pathname); ga(‘send’, ‘pageview’); чтобы изменить URL-адрес события просмотра страницы.

Возможно, есть способ сделать это более 'next.js', но сценарии запуска WRT на странице, я обнаружил, что если я создал компонент Script следующим образом:

// modules/Script.js
export default ({children}) => (
  <script dangerouslySetInnerHTML={{__html: `(${children.toString()})();` }}></script>
);

Тогда я мог бы сделать это, что сработало для меня:

import Document, { Head, Main, NextScript } from 'next/document'
import Script from '../modules/Script';

export default class MyDocument extends Document {

  render () {
    return (
      <html>
        <body>
          <Main />
          <Script>
            {
              () => {
                console.log('foo');
              }
            }
          </Script>
          <NextScript />
        </body>
      </html>
    )
  }
}

Предостережение заключается в том, что вы должны заключить все в функцию.

Можно ли отслеживать просмотры отдельных страниц без явного вызова ga ('send', 'pageview') на каждой странице. Если это абсолютно необходимо, где мы можем вызвать его, если мы уверены, что ga загружен?

Можно ли каким-то образом привязать события изменения маршрута к журналированию просмотров страниц?

@karthikiyengar Я использую react-ga как было предложено другими выше, и регистрирую просмотры страниц на componentDidMount каждой страницы.

import ReactGA from 'react-ga'

export const initGA = () => {
  console.log('GA init')
  ReactGA.initialize('UA-xxxxxxxx-x')
}
export const logPageView = () => {
  ReactGA.set({ page: window.location.pathname })
  ReactGA.pageview(window.location.pathname)
}
componentDidMount () {
    initGA()
    logPageView()
  }

@vinaypuppal - это обычная практика для initGA для каждого компонента страницы?

@rongierlach Я использую компонент Layout который вызывает методы initialize и pageview для ReactGA внутри componentDidMount() .

export default class extends Component {
  componentDidMount() {
    ReactGA.initialize('UA-1234567-1')
    ReactGA.pageview(document.location.pathname)
  }

  render() {
    return (
      <div>
        {this.props.children}
     </div>
    )
}

Это самый чистый способ, которым я это сделал, как будто страница отображается на сервере, ее нужно инициализировать. Я уверен, что есть ловушка, которая может обойти инициализацию, если она отображается клиентом.

@notrab, не могли бы вы пропустить неглубокие рендеры? Они просто перейдут в ваше приложение, и ваш компонент макета не сможет перемонтироваться. Вот что я должен поймать.

componentDidMount() {
    ReactGA.initialize('xx-xxxxxxx-x')
    let trackMe = true

    if (trackMe) {
      ReactGA.pageview(document.location.pathname)
      trackMe = false
    }

    Router.onRouteChangeStart = () => {
      NProgress.start()
      this.store.dispatch(transitionPage(true))
      trackMe = true
    }
    Router.onRouteChangeComplete = () => {
      NProgress.done()
      this.store.dispatch(transitionPage(false))
      if (trackMe) { ReactGA.pageview(document.location.pathname) }
    }
    Router.onRouteChangeError = () => {
      NProgress.done()
      this.store.dispatch(transitionPage(false))
    }

    this.store.dispatch(calculateResponsiveState(window))
  }

Пытаюсь заставить это работать, но все еще нет ответа от Google Analytics. Это мой код в react-ga.js :

import ReactGA from 'react-ga'

const dev = process.env.NODE_ENV !== 'production'

export const initGA = () => {
  ReactGA.initialize("UA-XXXXXXXXX-X", {
    debug: dev,
  })
}

export const trackPageView = (
  pageName = window.location.pathname + window.location.search
) => {
  ReactGA.set({page: pageName})
  ReactGA.pageview(pageName)
}

export const trackCustomEvent = (category, action) =>
  ReactGA.event({category, action})

export default undefined

И моя индексная страница:

import {initGA, trackPageView} from '../modules/react-ga.js'
[...]
Index.componentDidMount = function() {
    initGA()
    trackPageView()
}

с заменой кода UA на мой реальный код, конечно.

@filostrato Как ты это

@exogenesys Закончилось помещением этого в utils/analytics.js :

import ReactGA from 'react-ga'

const dev = process.env.NODE_ENV !== 'production'

export const initGA = () => {
  ReactGA.initialize("UA-xxxxxxxxx-x", {
    debug: dev,
  })
}

export const logPageView = (
  pageName = window.location.pathname + window.location.search
) => {
  ReactGA.set({page: pageName})
  ReactGA.pageview(pageName)
}

export const trackCustomEvent = (category, action) =>
  ReactGA.event({category, action})

export default undefined

и изменил мои Layout.js на React.Component :

export default class Layout extends React.Component {
    componentDidMount () {
      if (!window.GA_INITIALIZED) {
        initGA()
        window.GA_INITIALIZED = true
    }
    logPageView()
  }

  render () {
    return (
      <Main>
        <Header />
        {this.props.children}
      </Main>
    )
  }
}

Не нашел способа заставить его работать в компоненте, который использует getInitialProps , но поскольку Layout.js не работает, он работал нормально; Не знаю, что делать, если мне нужна более подробная статистика, но я перейду этот мост, когда подойду к нему.

@filostrato Вот и все. Большое спасибо. :)

Эй, ребята

Я только что занимался реализацией GA на моем сайте, и это то, что я придумал.

Сначала я использовал решение от @notrab, которое казалось простым и

export default class extends Component {
  componentDidMount() {
    ReactGA.initialize('UA-XXXXXXX-X')
    ReactGA.pageview(document.location.pathname)
  }

  render() {
    …
  }
}

Однако заметил:

  • componentDidMount был выполнен, когда я переключался между страницами разных типов, поэтому функция initialize вызывалась несколько раз
  • componentDidMount был _только_ выполняется , когда я переключался между страницами разных типов, так что pageview функция была вызвана только тогда => У меня есть video PageType на моем сайте , и я увидел в представление GA Live, в котором при переключении между разными страницами видео отслеживалась только начальная страница видео

Я создал компонент более высокого порядка для решения этих двух проблем. Для первого я использовал решение @filostrato .

import React, { Component } from 'react';
import ReactGA from 'react-ga';
import Router from 'next/router';

const debug = process.env.NODE_ENV !== 'production';

export default (WrappedComponent) => (
  class GaWrapper extends Component {
    constructor (props) {
      super(props);
      this.trackPageview = this.trackPageview.bind(this);
    }

    componentDidMount() {
      this.initGa();
      this.trackPageview();
      Router.router.events.on('routeChangeComplete', this.trackPageview);
    }

    componentWillUnmount() {
      Router.router.events.off('routeChangeComplete', this.trackPageview);
    }

    trackPageview (path = document.location.pathname) {
      if (path !== this.lastTrackedPath) {
        ReactGA.pageview(path);
        this.lastTrackedPath = path;
      }
    }

    initGa () {
      if (!window.GA_INITIALIZED) {
        ReactGA.initialize('UA-XXXXXX-XX', { debug });
        window.GA_INITIALIZED = true;
      }
    }

    render() {
      return (
        <WrappedComponent {...this.props} />
      );
    }
  }
);

И в вашем компоненте <Layout> / <PageWrapper> / <PageScaffold> или как вы его называете:

import GaWrapper from './ga-wrapper';

const PageScaffold = () => (…);

export default GaWrapper(PageScaffold);

Может быть, это кому-нибудь поможет.

Мне не нравится вызов Router.router.events.… , потому что это не часть документированного API. Однако, когда я попытался вызвать Router.onRouteChangeComplete который должен быть правильным , я получил ReferenceError, потому что onRouteChangeComplete было undefined . Может документация устарела?

Это сработало для меня на веб-сайте next.js. И обошел ошибку «окно не определено», с которой я столкнулся с обычной реализацией response-ga.

Решение @osartun сработало для меня. Спасибо! 👍

Благодаря коду @osartun я смог придумать следующее решение для pageview с использованием нового gtag от Google (который заменяет скрипты _universal analytics_):

pages/_document.js

import Document, { Head } from 'next/document';

const GA_TRACKING_ID = '..';

export default class MyDocument extends Document {
  render() {
    return (
      <html lang="en-AU">
        <Head>
          <script async src={`https://www.googletagmanager.com/gtag/js?id=${GA_TRACKING_ID}`} />
          <script
            dangerouslySetInnerHTML={{
              __html: `
                window.dataLayer = window.dataLayer || [];
                function gtag(){dataLayer.push(arguments)};
                gtag('js', new Date());
                gtag('config', '${GA_TRACKING_ID}');
              `,
            }}
          />
        </Head>
        ...
      </html>
    );
  }
}

scaffold.js / layout.js / wraper.js / как ни назови его проект:

import url from 'url';
import Router from 'next/router';

const GA_TRACKING_ID = '...';

const withPageViews = WrappedComponent =>
  class GaWrapper extends React.Component {
    componentDidMount() {
      // We want to do this code _once_ after the component has successfully
      // mounted in the browser only, so we use a special semiphore here.
      if (window.__NEXT_ROUTER_PAGEVIEW_REGISTERED__) {
        return;
      }

      window.__NEXT_ROUTER_PAGEVIEW_REGISTERED__ = true;
      let lastTrackedUrl = '';

      // NOTE: No corresponding `off` as we want this event listener to exist
      // for the entire lifecycle of the page
      // NOTE: This does _not_ fire on first page load. This is what we want
      // since GA already tracks a page view when the tag is first loaded.
      Router.router.events.on('routeChangeComplete', (newUrl = document.location) => {
        if (newUrl === lastTrackedUrl || !window.gtag) {
          return;
        }

        // Don't double track the same URL
        lastTrackedUrl = newUrl;

        // Believe it or not, this triggers a new pageview event!
        // https://developers.google.com/analytics/devguides/collection/gtagjs/single-page-applications
        window.gtag('config', GA_TRACKING_ID, {
          page_path: url.parse(newUrl).path,
        });
      });
    }

    render() {
      return <WrappedComponent {...this.props} />;
    }
  };

const PageScaffold = () => (…);

export default withPageViews(PageScaffold);

Для тех, кто опаздывает на вечеринку, причина, по которой решение @kylewiedman не работает, заключается в том, что события маршрутизатора определяются внутри componentDidMount . Их определение вне компонента, кажется, решает проблему:

https://gist.github.com/trezy/e26cb7feb2349f585d2daf449411d0a4

@trezy при использовании gtag , похоже, нет необходимости в import ReactGA from 'react-ga' .

Я использовал ваш пример <script dangerouslySetInnerHtml={...} /> и просто добавил эту строку в инъекцию:

window.gaTrackingId = '${gaTrackingId}';

Впоследствии этот легкий трюк начал работать:

Router.onRouteChangeComplete = () => {
  if (window.gtag) {
    window.gtag('config', window.gaTrackingId, {
      page_location: window.location.href,
      page_path: window.location.pathname,
      page_title: window.document.title,
    });
  }
};

Довольно большие analytics.js больше не выбираются, но все страницы по-прежнему отслеживаются!

Поскольку это неочевидно, было бы неплохо иметь пример в репо.

Или репозиторий next-google-analytics 🕵️

@prichodko Большое спасибо за составление этого примера !!

Официальный пример доступен здесь: https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics

нашел довольно красивую библиотеку, добавленную в основной файл макета в componentDidMount (), и, похоже, она работает правильно. Это хорошо задокументировано, без суеты

https://www.npmjs.com/package/react-gtm-module

@andylacko В самом деле, я https://github.com/Vadorequest/react-gtm

Просто добавляю здесь свое решение на случай, если оно может быть кому-то полезно позже.

Я использовал response-ga, но та же логика должна работать с другими инструментами ga.

_app.js getInitialProps запускается на стороне клиента всякий раз, когда пользователь щелкает новый маршрут. (В первый раз он будет работать на стороне сервера).

componentDidMount из _app.js работает только на стороне клиента.

Итак, в моем _app.js я добавил следующие несколько строк кода


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Когда страница отображается на сервере, в getInitialProps ничего не произойдет, поскольку я заключил код GA в typeof(window) === "object" .

На стороне клиента getInitialProps не запускается в первый раз, поскольку все обрабатывается сервером. GA настраивается внутри componentDidMount на стороне клиента.

Последующие изменения маршрута (даже для одного и того же маршрута) вызовут getInitialProps на стороне клиента и событие ga.

Просто добавляю здесь свое решение на случай, если оно может быть кому-то полезно позже.

Я использовал response-ga, но та же логика должна работать с другими инструментами ga.

_app.js getInitialProps запускается на стороне клиента всякий раз, когда пользователь щелкает новый маршрут. (В первый раз он будет работать на стороне сервера).

componentDidMount из _app.js работает только на стороне клиента.

Итак, в моем _app.js я добавил следующие несколько строк кода


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Когда страница отображается на сервере, в getInitialProps ничего не произойдет, поскольку я заключил код GA в typeof(window) === "object" .

На стороне клиента getInitialProps не запускается в первый раз, поскольку все обрабатывается сервером. GA настраивается внутри componentDidMount на стороне клиента.

Последующие изменения маршрута (даже для одного и того же маршрута) вызовут getInitialProps на стороне клиента и событие ga.

Привет, Уилл. Влияет ли включение ReactGA в ваш веб-пакет (поскольку он выполняется на стороне клиента) на размер вашей сборки?

@ChrisEdson https://github.com/react-ga/react-ga вся библиотека заархивирована на 161 КБ.

Хм. Честно говоря, это очень здорово!

В чт, 28 февраля 2019 г., в 19:01, Уильям Ли [email protected] написал:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga вся библиотека заархивирована на 161 КБ.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

это номер, указанный на GitHub для всей библиотеки.
Как проверить фактический размер после упаковки в приложении?

отправлено из моего Айфона

1 марта 2019 года в 15:43 Крис Эдсон [email protected] написал:

Хм. Честно говоря, это очень здорово!

В чт, 28 февраля 2019 г., в 19:01, Уильям Ли [email protected] написал:

@ChrisEdson https://github.com/ChrisEdson
https://github.com/react-ga/react-ga вся библиотека заархивирована на 161 КБ.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/zeit/next.js/issues/160#issuecomment-468395136 или отключить звук
нить
https://github.com/notifications/unsubscribe-auth/AC5okwth_o_BLLPeqIcSBmhKineAhYfgks5vSCeUgaJpZM4KkXxa
.

-
Вы получили это, потому что оставили комментарий.
Ответьте на это письмо напрямую, просмотрите его на GitHub или отключите обсуждение.

Таким образом, размер минифицированного скрипта составляет 15 КБ. Это довольно мало.

Я собираюсь проанализировать свой веб-пакет и доложить, сколько он добавляет на практике.

При общем размере пакета ~ 500 КБ мой ReactGA добавляет около 27 КБ. Такой маленький по большому счету.

Просто добавляю здесь свое решение на случай, если оно может быть кому-то полезно позже.

Я использовал response-ga, но та же логика должна работать с другими инструментами ga.

_app.js getInitialProps запускается на стороне клиента всякий раз, когда пользователь щелкает новый маршрут. (В первый раз он будет работать на стороне сервера).

componentDidMount из _app.js работает только на стороне клиента.

Итак, в моем _app.js я добавил следующие несколько строк кода


static async getInitialProps({ Component, router, ctx }) {
    let pageProps = {}

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);      
    }

    // client-side only, run on page changes, do not run on server (SSR)
    if (typeof(window) === "object") {
      ReactGA.pageview(ctx.asPath);
    }
    return { pageProps, router }
  }


  componentDidMount() {
    // client-side only, run once on mount
    ReactGA.initialize('UA-XXXXXXX-3');
    ReactGA.pageview(window.location.pathname + window.location.search);
  }

Когда страница отображается на сервере, в getInitialProps ничего не произойдет, поскольку я заключил код GA в typeof(window) === "object" .

На стороне клиента getInitialProps не запускается в первый раз, поскольку все обрабатывается сервером. GA настраивается внутри componentDidMount на стороне клиента.

Последующие изменения маршрута (даже для одного и того же маршрута) вызовут getInitialProps на стороне клиента и событие ga.

Проблема, возникающая при использовании NextJS 9, заключается в том, что при этом отключен автоматический предварительный рендеринг. Если интересно, есть ли лучшее место для размещения ReactGA.pageview(ctx.asPath); , удаление его из getInitialProps означает, что мы можем удалить getInitialProps и не принудительно отключить автоматический предварительный рендеринг, как описано здесь: https : //err.sh/next.js/opt-out-automatic-prerendering.

Обновление: я нашел пример with-google-analytics (https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics) и позаимствовал бит примерно: Router.events.on('routeChangeComplete', url => ReactGA.pageview(url)) Мне нужно проверить это, чтобы убедиться, что URL-адрес правильный, но выглядит правильным. Я удалил метод getInitialProps и добавил его над объявлением класса.

@GodOfGrandeur Звучит многообещающе, попробую в прод. Не удалось заставить версию, упомянутую выше, работать или казалось так https://medium.com/@austintoddj/using -google-analytics-with-next-js-423ea2d16a98 Добавление вашего кода в _app.js, кажется, запускается везде, как необходимо и мне также нравится, что он не запускается на сервере (не было бы, хотя это проблема).

Нет необходимости в какой-либо третьей стороне. Если вы используете gtag, используйте следующий код, который я создал: -

<script
    async
    src="https://www.googletagmanager.com/gtag/js?id=%your code here%" >
</script>
<script dangerouslySetInnerHTML={
    { __html: `
        window.dataLayer = window.dataLayer || [];
        function gtag(){window.dataLayer.push(arguments)}
        gtag("js", new Date());
        gtag("config", "<%your code here%>");
    `}
}>
</script>

Другой вариант - использовать useEffect() . Я сделал это в своем файле Layout.js .

useEffect(() => {
  if (process.env.NODE_ENV === 'production') {
    window.dataLayer = window.dataLayer || []
    function gtag() {
      dataLayer.push(arguments)
    }
    gtag('js', new Date())
    gtag('config', '{GOOGLE ANALYTICS CODE}', {
      page_location: window.location.href,
      page_path: window.location.pathname,
      page_title: window.document.title,
    })
  }
})

И в <Head> :

<Head>
  <script async src="https://www.googletagmanager.com/gtag/js?id={GOOGLE ANALYTICS CODE}"></script>
</Head>

@reinink Просто хочу упомянуть, что вы можете передать пустой массив в качестве второй опоры в useEffect чтобы он запускал функцию только один раз после первоначального рендеринга.

useEffect(() => {...}, [])

Расширяя решение @reinink , вот рабочий HOC, который я использую для упаковки компонентов / шаблонов макета.

import React, { useEffect } from 'react'
import Head from 'next/head'
const GoogleAnalyticsHOC = ({ children }) => {
  useEffect(() => {
    if (process.env.NODE_ENV === 'production') {
      window.dataLayer = window.dataLayer || []
      // eslint-disable-next-line
      function gtag() {
        window.dataLayer.push(arguments)
      }
      gtag('js', new Date())
      gtag('config', process.env.GOOGLE_ANALYTICS_ID, {
        page_location: window.location.href,
        page_path: window.location.pathname,
        page_title: window.document.title
      })
    }
  }, [])
  return (
    <>
      <Head>
        <script async src={`https://www.googletagmanager.com/gtag/js?id=${process.env.GOOGLE_ANALYTICS_ID}`} />
      </Head>
      {children}
    </>
  )
}
export default GoogleAnalyticsHOC

Он не тестировался всесторонне, но работает и выдает себя за посетителя в реальном времени, работающего локально. :)

Я нашел это руководство - это рекомендуемый подход (использует react-ga)?

Я бы сказал, что рекомендуемый способ - использовать этот официальный пример:

https://github.com/zeit/next.js/tree/canary/examples/with-google-analytics

Это уже размещено здесь. Иногда я хочу, чтобы проблемы с github были больше похожи на stackoverflow, чтобы какой-то ответ был принят и выделен сразу после вопроса (когда слишком много сообщений и смайликов недостаточно. Один из вариантов - ограничить комментирование этого сообщения, чтобы люди создавали новую проблему вместо этого. И при создании они обнаружат, что аналогичная проблема уже была создана (благодаря функции «похожие проблемы»), и на нее есть ответ (но все же ответ с помощью эмодзи потерялся где-то в середине долгой истории, так что это не очень удобно ответы на гитхабе).

Это уже размещено здесь. Иногда я хочу, чтобы проблемы с github были больше похожи на stackoverflow, чтобы какой-то ответ был принят и выделен сразу после вопроса (когда слишком много сообщений и смайликов недостаточно ...

Github создает прототип на вкладке « Обсуждения » этого репозитория.

Screenshot 2020-04-08 at 16 59 58

@janbaykara вау, правда? Мы все думаем одинаково :) Я надеюсь, что они найдут способ каким-то образом перевести проблему в обсуждение, или это будет то же самое (если функциональность будет объединена с проблемами, и все существующие обсуждения станут проблемами). Но спасибо за ответ!

@ 3lonious Я лично отказался от Google Analytics, так как в целом он не очень хорошо справляется со SPA. (действительно плохой опыт, особенно с SSR + CSR и двойными событиями, которые трудно отследить)

Что касается Next.js, посетите https://github.com/UnlyEd/next-right-now/blob/v2-mst-aptd-gcms-lcz-sty/src/components/pageLayouts/Head.tsx (используя next/Head ), вот как я включаю теги скриптов в свои приложения.

Не стесняйтесь взглянуть на NRN https://unlyed.github.io/next-right-now , он призван стать хорошим примером того, «как делать X» с Next.js и должен избавить вас от головной боли.

Я не уверен, что понял, я не вижу никаких тегов скрипта в этом файле?

Это тоже решение, которое работает. Я не тестировал это подробно, поэтому сделайте это самостоятельно.

В pages/_document.js добавьте это к <Head> . См. Документацию о том, как переопределить файл документа .

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

            gtag('config', 'YOUR_GA_TRACKING_ID');
              `
      }}>
</script>

По крайней мере, он сообщает трафик моей учетной записи GA.

Теги @ 3lonious Script и теги стиля работают одинаково.
Вышеупомянутое решение также работает, исходя из опыта. (так я заставлял GA работать)

хорошо, спасибо, ребята. Я попытаюсь вернуться к тебе

хорошо, я думаю, у меня это работает

спасибо Антон. хорошо, у меня есть новый для тебя, ха-ха

У меня есть приложение для чата, которое я использую для обслуживания клиентов, но этот тег скрипта тоже не работает? есть идеи?

он говорит мне добавить этот второй тег в тело? что ты с этим делаешь?
Screen Shot 2020-06-19 at 6 48 22 AM

Как насчет TBT? Если вы добавите Google Analytics, это снизит ваш показатель скорости

Как насчет TBT? Если вы добавите Google Analytics, это снизит ваш показатель скорости

Это из-за их рекомендации размещать сценарий перед контентом. Если вы разместите его под контентом, оценка не снизится.

Я лично не вижу реальной пользы от размещения сценария первым. Если загрузка страницы каким-то образом прервалась, а HTML каким-то образом не загрузился полностью и был прерван, я мог бы не считать это попаданием, и так далее.

Я работаю с nextjs. Я пытаюсь использовать реакцию автозаполнения Google Place API. И хочет вставить тег скрипта API? Куда мне вставить этот тег скрипта ??

_app.js

`` js
импортировать ReactGA из "react-ga";

componentDidMount() {
  ReactGA.initialize("XX-XXXXXXXXX-X", { debug: false });
  ReactGA.set({ page: this.props.router.pathname });
  ReactGA.pageview(this.props.router.pathname);
  this.unlisten = this.props.router.events.on("routeChangeComplete", (router) => {
      ReactGA.set({ page: router });
      ReactGA.pageview(router);
    });
}

Это весело. Нет, вообще-то это печально. Не могу дождаться, когда React, Next, вся экосистема умрет.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

swrdfish picture swrdfish  ·  3Комментарии

wagerfield picture wagerfield  ·  3Комментарии

rauchg picture rauchg  ·  3Комментарии

havefive picture havefive  ·  3Комментарии

renatorib picture renatorib  ·  3Комментарии