Git Product home page Git Product logo

piwik-react-router's Introduction

Piwik React Router

npm package dependency status Build Status Coverage Status

Piwik analytics component for react-router

Installation

npm install piwik-react-router --save

or

yarn add piwik-react-router

Features

  • asynchronous loading of Piwik
  • javascript error tracking
  • low level access to piwik.push()

Usage

Simply create your instance with the same url and siteId as described in the piwik documentation and connect it to your history object.

Starting with v2.0 react-router won't provide a default history. Why?.

const PiwikReactRouter = require('piwik-react-router');

const piwik = PiwikReactRouter({
	url: 'your-piwik-installation.com',
	siteId: 1
});

/**
 * Create your history in advance. Please head over to the react-router FAQ for more infos:
 * @see https://github.com/ReactTraining/react-router/blob/master/FAQ.md#how-do-i-access-the-history-object-outside-of-components
*/
<Router history={piwik.connectToHistory(history)}>
	<Route path="/" component={MyComponent} />
</Router>

If you're using react-router prior to v1.0 please head over to the react-router0.13.x branch.

For the url-option you can also include http:// or https:// in the beginning of the url, if you piwik installation is on ssl, but your react-site is not, or visa versa.

Options

enableLinkTracking: true

Link tracking to track outgoing and download links is enabled by default.

userId: undefined

User ID to associate every request with a username or email. More information here: User ID

updateDocumentTitle: true

Updates the document title before adding a new page view as the title may changed during the route rendering. Make sure you call piwik.track after React has rendered the <Handler /> to make this work correctly. If you don't know how to update the title, check out the great react-document-title or react-helmet module.

trackErrors: false

By enabling this option occurring javascript errors will be tracked as a JavaScript Error piwik event.

see http://davidwalsh.name/track-errors-google-analytics for further details

trackErrorHandler: [default error handler]

Set a custom error handler for javascript errors, allowing custom formatting of events published when an error occurs.

see Tracking Events for further details

ignoreInitialVisit: false

By enabling ignoreInitialVisit it connects to the history without tracking the initial visit.

injectScript: true

By disabling injectScript the piwik.js script will not be injected automatically to allow a separate loading.

Starting with version 0.12.0 the usually required options siteId and url are now optional if a running instance of the piwik tracking script is detected by validating the following cases:

  • A <script> src matches the url defined via opts.url and opts.clientTrackerName
  • siteId and setTrackerUrl calls are already present in window._paq

clientTrackerName: 'piwik.js'

The name of the piwik.js static resource on the Piwik server. Set this option if the Piwik instance uses a different name.

serverTrackerName: 'piwik.php'

The name of the piwik.php script on the Piwik server. Set this option if the Piwik instance uses a different name.

API

track (Location location)

Adds a page view from a history Location if the path changed.

path = location.pathname + location.search

push (args)

Pushes the specified args to the Piwik tracker the same way as you're using the _paq.push(args); directly. You can use this method as the low-level api to call methods from the Piwik API, track events or call custom functions.

setUserId (userId)

Sets the specified user id to the Piwik tracker after PiwikReactRouter has been initialized. It wraps around the 'setUserId' method of Piwik User ID

trackError (error, [eventName])

Tracks the given error as a new Piwik Event for the given event name. If you don't specify any name here it will fallback to JavaScript Error.

The handler is overriden if the trackErrorHandler option is set.

connectToHistory(history, [modifier])

Adds a listener to the passed in history to trigger track(location) whenever the history changes. The optional modifier function (added in version 0.9.0) acts as a proxy to allow the modification of the given location before the track(location) function is called.

const modifier = function (location) {
	location.search = 'campain=ID';

	return location;
}

<Router history={piwik.connectToHistory(history, modifier)}>

Connecting to the history also tracks the location of the initial visit since release 0.7.0 if not manually disabled via ignoreInitialVisit

disconnectFromHistory()

Disconnects Piwik from a previous connected history. Returns whether it could successfully disconnect.

A note on serverside rendering

Piwik tracking is disabled for serverside rendering and all API methods are replaced with noop-functions so you don't have to worry about it.

piwik-react-router's People

Contributors

caalberts avatar gerhardsletten avatar joernroeder avatar jthomaschewski avatar karlhorky avatar linkiwi avatar lubergalexander avatar mrroyce avatar tbtz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

piwik-react-router's Issues

Feature request: Being able to skip initialization of Piwik

Hi

Our web app assembl adds dynamically a piwik tracking script to the DOM of its pages, if an administrator has activated piwik tracking and has provided a piwik site id in the administration panel.

So, as we are progressively migrating our application to React, we would like to use piwik-react-router to track user navigation in React routes, but using an already initialized Piwik tracking script.

I think this solution is better than a solution where we would try to get our piwik configuration data from our application server and then use this data to initialize piwik-react-router.

And I see no other solution than these 2 for now.

Do you have any ideas about this type of use case? I will provide a pull request with the changes we made to skip piwik initialization.

Edit: I provided a PR here: #42

You cannot change <Router history>

I am getting the following warning and hot-reloading is broken since implementing piwik-react-router:

backend.js:6 Warning: You cannot change Router history

This is my App.js where I call connectToHistory()

import React, { Component } from "react";
import PropTypes from "prop-types";

import { withRouter, Router, Switch, Route } from "react-router-dom";
import { createBrowserHistory } from "history";
import { library } from "@fortawesome/fontawesome-svg-core";
import MatomoTracker from "piwik-react-router";

import {
...
} from "@fortawesome/free-solid-svg-icons";
import { Button } from "react-bootstrap";
import { bootstrapUtils } from "react-bootstrap/lib/utils";
import { hot } from "react-hot-loader";

import Login from "./pages/login/Login";
import Main from "./Main";
import ProtectedRoute from "../routes/ProtectedRoute";

library.add(
...
);

bootstrapUtils.addStyle(Button, "ace");

export const matomo = MatomoTracker({
  url: "analytics.ace",
  siteId: 1
});

class App extends Component {
  render() {
    let history = createBrowserHistory();
    if (process.env.mode === "production") {
      history = matomo.connectToHistory(createBrowserHistory());
    }
    // We need this as long as react-router-bootstrap is not updated
    // to be compatible with react-router-bootstrap v5
    // see for more info: https://github.com/react-bootstrap/react-router-bootstrap/issues/250
    const RouterContextProvider = withRouter(
      class extends React.Component {
        static childContextTypes = {
          router: PropTypes.object
        };

        getChildContext() {
          const { children, ...router } = this.props;
          return { router };
        }

        render() {
          return this.props.children;
        }
      }
    );

    return (
      <>
        <Router history={history}>
          <RouterContextProvider>
            <Switch>
              <Route component={Login} exact path="/login" />
              <ProtectedRoute component={Main} path="/" />
            </Switch>
          </RouterContextProvider>
        </Router>
      </>
    );
  }
}

export default hot(module)(App);

What could be causing this? Let me know if you need any other info.

`PiwikTracker.track` sends URLs with appended slash

url-join had a bug, leading to an additional "/" that was appended to the URL send with PiwikTracker.track.

# with url-join 1.1.0
$ node -pe "require('url-join')('/path', '')"
/path/
$ node -pe "require('url-join')('/', '')"
//

# with url-join 4.0.0
$ node -pe "require('url-join')('/path', '')"
/path
$ node -pe "require('url-join')('/', '')"

Piwik React Router has url-join currently locked at version ^1.1.0, so an update should fix this.

Is there a specific reason why urljoin(loc.pathname, loc.search) is used instead of loc.pathname + loc.search?

Dynamic piwik URL

@joernroeder have you come across a situation where you need to use environment-dependent piwik URLs in different environments, e.g staging, production? If so, how do you go about setting them

TypeError: Cannot read property 'parentNode' of undefined

I am creating a ReactJS application and I am using piwik-react-router. Everything is running ok. However, when I run a simple test on my App.js, I get the following error:

TypeError: Cannot read property 'parentNode' of undefined
 
      at node_modules/piwik-react-router/index.js:171:6
      at PiwikTracker (node_modules/piwik-react-router/index.js:173:4)
      at Object.<anonymous> (src/components/App.js:14:46)
      at Object.<anonymous> (src/components/App.test.js:3:12)
          at Generator.next (<anonymous>)
          at new Promise (<anonymous>)
      at handle (node_modules/worker-farm/lib/child/index.js:44:8)
      at process.<anonymous> (node_modules/worker-farm/lib/child/index.js:51:3)
      at emitTwo (events.js:126:13)
      at process.emit (events.js:214:7)
      at emit (internal/child_process.js:772:12)
      at _combinedTickCallback (internal/process/next_tick.js:141:11)
      at process._tickCallback (internal/process/next_tick.js:180:9)

I am using jest to run my tests, and I tried to run the default test found here

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => {
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
});

I import piwik in my App.js like this:
import PiwikReactRouter from 'piwik-react-router';

The error in piwik-react-router/index.js is on line 171 when it is trying to access s.parentNode. The s is a script element that it just created and got like this:

var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];

I have set my jest environment to be jsdom, however, it seems that it still cannot find the script.
Is this a known issue? What can I do about this?

connectToHistory typescript definition does not accept same arguments as the function.

The exported typescript definition reads:

connectToHistory<H extends LooseHistory>(history: H): H;

But in react-router-piwik.js the function is defined as:

connectToHistory(history, trackAtConnect, callback)

I can supply those extra arguments and it works, but my IDE complains about a typescript mismatch:

2021-10-29_00-49-36

I think at some point the function got extra arguments and someone forgot to update the typescript exported definition?

I even think that if you call it with just one argument, it errors, because it tries to call that callback function (third argument).

tracking not working

Hi, I have question about this package.
I am using react router 4 so I have used the createBrowserhistory to create the history. This is the App.js file

import React from "react";
import { BrowserRouter } from "react-router-dom";
import { createBrowserHistory } from "history";
import Root from "./Root";
import config from "./config";
const PiwikReactRouter = require("piwik-react-router");

const matomoSiteId = config.matomoSiteId ? config.matomoSiteId : 3;
const matomoUrl = config.matomoUrl ? config.matomoUrl : "";

function App() {
  const piwik = PiwikReactRouter({
    url: matomoUrl,
    siteId: matomoSiteId,
  });
  const history = createBrowserHistory();

  return (
    <BrowserRouter history={piwik.connectToHistory(history)}>
      <Root />
    </BrowserRouter>
  );
}

export default App;

And in the index.html I am using the Matomo Tag manager and in my Matomo board I have configured a Matomo Analytics tag to track the navigation in my React web App

However we I click on the links in the navigation bar, the page URL is not tracked. Is there anything else I should do?

add optional proxy function argument to .connectToHistory

As i proposed in #39 i'd like to add a second (optional) argument to the .connectToHistory method. The optional function should act like a proxy and allows the modification of the given location object from the history before it gets passed down to the .track method.

Can't find variable: document

Maybe i am using this plugin entirely wrong but i am trying to use it in a react native app. But when i add

var PiwikReactRouter = require('piwik-react-router');

var piwik = PiwikReactRouter({
      url: '127.0.0.1/piwik',
      siteId: 1
    });

It just results in a red page saying "Can't find variable: document"

Feature request: Allow setting of custom error tracking handler

Hi,

At oradian we found ourselves in need of using some custom error handling/transformation logic, which we couldn't do with the default error tracking handler. Therefore, we added and documented an init option to set your own custom handler, which is then invoked in places where the old, default, handler would be invoked.

If you think you can make use of this in your project, see PR #43 for details.

Option to configure name of Piwik resources

I'm proposing the addition of fields to the existing options object of PiwikReactRouter to allow specification of the name of the Piwik JS and PHP resources.

Currently, they are hardcoded as piwik.js and piwik.php.

However, in my personal instance of Piwik, these files are main.js and main.php, respectively. It would be nice if this module allowed the user to configure the names of these files, rather than defaulting to piwik.

Is this a valid, general-purpose use case? I'm happy to submit a PR to add this functionality if you believe it is general enough. I also understand that this is a pretty narrow, installation-specific requirement so please feel free to close this issue if it applies too narrowly.

React-Router 1.0 and piwik-react-router integration

Prior to 1.0, with the version 0.13.2 of React-Router we had an easy way to track user navigation using this library utility, by passing the router state directly to the utility, so that any time user changed the route, the line PiwikUtil.track(state) was executed:

Router.run(routes, Router.HistoryLocation, function(Handler, state) {
  React.render(<Handler title="app.title" urlParams={state.params} urlQuery={state.query}/>, document.getElementById('app'));
    PiwikUtil.track(state);
});

Are you guys planning to upgrade the library to the version 1.0?

Anyway, we had to upgrade the codebase to the version 1.0 of React-Router and they way I came up to work the problem around was to use onEnter callbacks to all the children routes, since there I have access to the router state. But that would imply to add the callback every time I add a new route. Do you think is there a better way to achieve that, such as with the previous version?

function trackRoute(nextState, replace) {
  PiwikUtil.track(nextState);
}

var routes = (
    <Route path={root} component={App} >
      <IndexRoute component={Component1} onEnter={trackRoute} />
      <Route path={root + '/filters/:filters'} component={Component1} onEnter={trackRoute}/>
      <Route path={root + "/detail/:id"} component={Component2} onEnter={trackRoute} />
      <Route path={root + "/detail/:id/:tab"} component={Component2} onEnter={trackRoute} />
      <Route path={root + "/create"} component={Component3} onEnter={trackRoute} />
    </Route>
    );

React.render(<Router history={history}>{routes}</Router>, document.getElementById('app'));

Page title updating past track event?

I'm having a bit of trouble with having react-helmet work with piwik-react-router. As listed in this issue, piwik-react-router is not waiting until the page renders before sending a track request. This results in the request having an incorrect action_name (or document title) being sent.

Any assistance in this matter would be greatly appreciated. Thanks!

Initial visit is not reported (only url changes are reported)

If I connect piwik and visit my website, nothing is reported to piwik. But when I click internal links on my page, then piwik shows me a new visit and action.

Could it be that piwik-react-router is only listening to changes, and not to the initial route?

Incorrect url in Piwik when use hashHistory from react-router

Page url address - https://domain.com/context/#/form?lang=en

In Piwik url register as https://domain.com/form?lang=en

I use hashHistory from react-router in my app.
piwik-react-router send push(['setCustomUrl', currentPath]), currentPath is calculate as
currentPath = urljoin(loc.pathname, loc.search) and for my url currentPath is /form?lang=en

Piwik calculate url https://github.com/piwik/piwik/blob/3.x-dev/js/piwik.js#L3275 and when url is absolute add only schema and host

if (url.slice(0, 1) === '/') {
    return getProtocolScheme(baseUrl) + '://' + getHostName(baseUrl) + url;
}

and i get my incorrect url https://domain.com/form?lang=en

Solving the problem would be for example remove initial slash depending on the parameter.

What do You think about it?

React Router v4 Support

Is there an appetite for adding react router 4 (or 2/3) support? Not many apps are still on v1. If not is there an alternative to using Matomo with react?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.