简体   繁体   English

使用 next.js 监听路由变化以与 matomo/piwik 一起使用

[英]Listen to route change with next.js to use with matomo/piwik

I'm trying to listen to route changes on a next.js app, in order to log navigation to matomo (aka piwik).我正在尝试收听 next.js 应用程序上的路线更改,以便将导航记录到 matomo(又名 piwik)。 According to next.js' documentation, I have to do something like this:根据 next.js 的文档,我必须这样做:

Router.events.on('routeChangeStart', url => {
  // Do something
});

Where do I have to use this code in my app in order to log all the route change events?我必须我的应用程序中的什么地方使用此代码才能记录所有路线更改事件?

( "where" means in which file/class/method) “where”表示在哪个文件/类/方法中)

You have to add it in pages/_app.js , in the componentDidMount method:您必须将它添加到pages/_app.js中的componentDidMount方法中:

componentDidMount() {
  Router.events.on("routeChangeStart", url => {
    if (window && window._paq) {
      window._paq.push(["setCustomUrl", url]);
      window._paq.push(["setDocumentTitle", document.title]);
      window._paq.push(["trackPageView"]);
    }
  });
}

Don't forget to initialize it in your base page (ie your Layout or something like that):不要忘记在您的基本页面(即您的布局或类似内容)中 对其进行 初始化

<!-- Matomo -->
<script type="text/javascript">
  var _paq = window._paq || [];
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="//{$PIWIK_URL}/";
    _paq.push(['setTrackerUrl', u+'piwik.php']);
    _paq.push(['setSiteId', {$IDSITE}]);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<!-- End Matomo Code -->

@rap-2-h answer worked great. @rap-2-h 的回答效果很好。 For including the script in your base page, you can include the matomo script as dangerouslySetInnerHTML inside next.js <Head> component like this:对于包括在你的基本页面的脚本,可以包括matomo脚本dangerouslySetInnerHTML内next.js <Head>这样的组件:

//import next had
import Head from 'next/head'

export default class Meta extends Component {

    render() {

        return (
          <Head>
            <script type="text/javascript" dangerouslySetInnerHTML={{
                    __html: ` var _paq = window._paq || [];
                    /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
                    _paq.push(['trackPageView']);
                    _paq.push(['enableLinkTracking']);
                  (function () {
                        var u = "https://your_matomo_link";
                        _paq.push(['setTrackerUrl', u + 'matomo.php']);
                        _paq.push(['setSiteId', '1']);
                        var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
                        g.type = 'text/javascript'; g.async = true; g.defer = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
                    })();
                `}} />

    </Head>
    )
   }
}

Then add it at the top of your layout or wherever然后将它添加到布局的顶部或任何地方

I got it to work like this我让它像这样工作

LayoutDefault.js布局默认.js

import NextHead from 'next/head'

export default function LayoutDefault() {
return (
    <div>
        <NextHead>
            …
            <script dangerouslySetInnerHTML={{ __html: `
                console.log('Matomo Component')

                var _paq = window._paq = window._paq || [];
                _paq.push(['trackPageView']);
                _paq.push(['enableLinkTracking']);
                (function() {
                    var u="{$MATOMO_URL}";
                    _paq.push(['setTrackerUrl', u+'matomo.php']);
                    _paq.push(['setSiteId', {$IDSITE}]);
                    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
                    g.type='text/javascript'; g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
                })();
            ` }} />
        </NextHead>
    </div>
)
}

_app.js _app.js

import { useEffect } from 'react'
import { useRouter } from 'next/router'

export default function MyApp({ Component, pageProps }) {
const router = useRouter()

useEffect(() => {
    const handleRouteChange = (url) => {
        if (window && window._paq) {
            _paq.push(['setCustomUrl', url]);
            _paq.push(['setDocumentTitle', document.title]);
            _paq.push(['trackPageView']);
        }
    }

    router.events.on('routeChangeStart', handleRouteChange)
}, [])

return <Component {...pageProps} />
}

To add on top of other answers: You should use the routeChangeComplete event over routeChangeStart in order to get the correct data - with routeChangeStart you will get the page title/url of the previous page.添加其他答案:您应该在 routeChangeStart 上使用 routeChangeComplete 事件以获得正确的数据 - 使用 routeChangeStart 您将获得上一页的页面标题/ url。

Complete solution:完整的解决方案:

_app.js as a functional component: _app.js 作为功能组件:

import { useRouter } from 'next/router'
import { useEffect } from 'react'

export default function App({ Component, pageProps }) {
    const router = useRouter()
    useEffect(() => {
        const handleRouteChange = (url) => {
            if (window && window._paq) {
                _paq.push(['setCustomUrl', url]);
                _paq.push(['setDocumentTitle', document.title]);
                _paq.push(['trackPageView']);
            }
        }

        router.events.on('routeChangeComplete', handleRouteChange)
    }, [])

    return (
        //your code
    )
}

layout.js:布局.js:

import Head from 'next/head'

export default function Layout({ children }) {
    return (
        <>
            <Head>
                <script type="text/javascript" dangerouslySetInnerHTML={{__html: `
                    var _paq = window._paq = window._paq || [];
                    _paq.push(['trackPageView']);
                    _paq.push(['enableLinkTracking']);
                    (function() {
                    var u="//<YOUR_MATOMO_URL>";
                    _paq.push(['setTrackerUrl', u+'matomo.php']);
                    _paq.push(['setSiteId', '1']);
                    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
                    g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
                    })();
                `}} />
            </Head>
            //your code
        </>
    )
}

Alternatively you can use Script from next/script and enclose the js within instead.或者,您可以使用 next/script 中的脚本,并将 js 包含在其中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM