matomo-tracker icon indicating copy to clipboard operation
matomo-tracker copied to clipboard

Integrate it with react.Router history

Open KrzysztofMadejski opened this issue 4 years ago • 2 comments

Is your feature request related to a problem? Please describe. I was expecting this lib to integrate with React Router out of the box, such as https://github.com/guillaumeparis2000/react-piwik :

<Provider store={store}>
    <Router routes={routes} history={piwik.connectToHistory(history, trackAtConnect)} />
  </Provider>,

Describe the solution you'd like I'd like sth similar as above or at least a README on how to listen to history events and track pageViews on history changes.

Describe alternatives you've considered Choosing another lib or implementing it myself.

KrzysztofMadejski avatar Feb 11 '21 16:02 KrzysztofMadejski

Implementing it was quite fast:

import { MatomoProvider, createInstance } from '@datapunt/matomo-tracker-react';
import { getRuntimeEnvVar } from 'helpers';
import { useEffect } from 'react';
import { useLocation } from 'react-router';

export const createClient = () => {
  const host = getRuntimeEnvVar('REACT_APP_RUNTIME_MATOMO_HOST');
  const siteId = parseInt(getRuntimeEnvVar('REACT_APP_RUNTIME_MATOMO_SITE_ID'));

  return createInstance({
    urlBase: host,
    siteId: siteId,
    // userId: 'UID76903202', // optional, default value: `undefined`. // TODO CDC-1389
    trackerUrl: `${host}/piwik.php`, // optional, default value: `${urlBase}matomo.php`
    srcUrl: `${host}/piwik.js`, // optional, default value: `${urlBase}matomo.js`
    heartBeat: { // optional, enabled by default
      active: true, // optional, default value: true
      seconds: 30 // optional, default value: `15
    },
    linkTracking: true, // optional, default value: true
    configurations: { // optional, default value: {}
      // any valid matomo configuration, all below are optional
      // disableCookies: true,
      setSecureCookie: true,
      setRequestMethod: 'POST'
      // TODO POST is default, but we would need to setup CORS: https://developer.matomo.org/api-reference/tracking-javascript
    }
  })
}

/**
 * MatomoRouterProvider provides Matomo hooks for children components
 * and it tracks page views on location change.
 * 
 * It should be embedded within <Router>
 */
export const MatomoRouterProvider = (
  {children}: {children: JSX.Element}) => {
  const isEnabled = getRuntimeEnvVar('REACT_APP_RUNTIME_MATOMO_ENABLED');
 
  if (!isEnabled) {
    return children;
  }

  const matomoClient = createClient();

  let location = useLocation();
  useEffect(() => {
    // track page view on each location change
    matomoClient.trackPageView()
  }, [location]);

  return (
    <MatomoProvider value={matomoClient}>
      {children}
    </MatomoProvider>
  )
}

/**
 * withMatomo is an HOC to wrap other component in order to provide Matomo to children
 * 
 * It does not integrate with react-router
 * 
 * @param Child 
 */
export const withMatomo = <T,>(Child: React.ComponentType<T>) => {
    const isEnabled = getRuntimeEnvVar('REACT_APP_RUNTIME_MATOMO_ENABLED');

    if (!isEnabled) {
      return Child;
    }

    const matomoClient = createClient();
  
    return (props: T) => (
        <MatomoProvider value={matomoClient}>
          <Child {...props}/>
        </MatomoProvider>
    );
}

KrzysztofMadejski avatar Feb 11 '21 21:02 KrzysztofMadejski

We might be able to make this a separate package to connect the two together. At the moment we are busy with the new API design and migrating some internal applications, so this is on the back-burner for now.

As mentioned by @KrzysztofMadejski, it's pretty trivial to add this in the application code. So we are going to recommend doing so for now.

jonkoops avatar Feb 15 '21 15:02 jonkoops