timlrx / tailwind-nextjs-starter-blog

This is a Next.js, Tailwind CSS blogging starter template. Comes out of the box configured with the latest technologies to make technical writing a breeze. Easily configurable and customizable. Perfect as a replacement to existing Jekyll and Hugo individual blogs.
https://tailwind-nextjs-starter-blog.vercel.app/
MIT License
8.56k stars 1.99k forks source link

Add support for Matomo Analytics #724

Open anmorgunov opened 11 months ago

anmorgunov commented 11 months ago

Matomo (formerly Piwik) is arguably the most well-established open-source alternative to Google Analytics. There's a package which allows for an easy use of Matomo with NextJS projects:

https://www.npmjs.com/package/@socialgouv/matomo-next

I use it in my other NextJS projects by creating the following component:

import { init } from "@socialgouv/matomo-next";
import { useEffect } from "react";

const MATOMO_URL = process.env.NEXT_PUBLIC_MATOMO_URL || "";
const MATOMO_SITE_ID = process.env.NEXT_PUBLIC_MATOMO_SITE_ID || "";

const Matomo = () => {
    useEffect(() => {
        init({url: MATOMO_URL, siteId: MATOMO_SITE_ID});
    });
    return null;
}

export default Matomo;

And importing it in _app.js as:

import dynamic from 'next/dynamic'

const Matomo = dynamic(() => import('../components/matomo'), {
  ssr: false
})

I couldn't integrate this into the app/layout.tsx because you can't use client-side "useEffect" in the server-side files. Perhaps there's an easy way to solve this, but my understanding of NextJS is somewhat limited.

timlrx commented 11 months ago

The way I tend to do it is to use the nextjs Scripts component e.g. https://github.com/timlrx/pliny/blob/main/packages/pliny/src/analytics/GoogleAnalytics.tsx

Will file it as a feature request and may pick it up on pliny's side.

anmorgunov commented 11 months ago

So if Matomo's tracking code looks like this:

<!-- Matomo -->
<script>
  var _paq = window._paq = window._paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="//domain.com/";
    _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);
  })();
</script>
<!-- End Matomo Code -->

Would MatomoAnalytics.tsx in pliny look like this?

import Script from 'next/script.js'

export interface MatomoProps {
  matomoHostUrl: string,
  matomoSiteId: string,
}

export const MA = ({ matomoHostUrl, matomoSiteId }: MatomoProps) => {
  return (
    <>
      <Script strategy="afterInteractive" id="ma-script">
        {`
            window.dataLayer = window.dataLayer || [];
            var _paq = window._paq = window._paq || [];
            _paq.push(['trackPageView']);
            _paq.push(['enableLinkTracking']);
            (function() {
              var u="//${matomoHostUrl}/";
              _paq.push(['setTrackerUrl', u+'matomo.php']);
              _paq.push(['setSiteId', '${matomoSiteId}']);
              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);
            })();
        `}
      </Script>
    </>
  );
};