
react-tracker 
- React specific tracking library, usable as a higher-order component
- Flexible-scalable solution for tracking in React Apps
- Easy to use (Redux-like)
- Can be pluged with any Analytics platform agnostic lib (You can mainly do anything in the event listeners callback)
Installation
npm install --save react-tracker
This assumes you are using npm as your package manager.
The Gist
The idea is to only provide one Tracker!
Why? because at some you'll need to apply some restriction on some events E.g. :
- Track product click only once!
- Track product click only if page views is already tracked
in these case we need to have the tracking history.. that's why we keep the history synced by providing the same instance of tracker to all components
import { Tracker } from 'react-tracker';
function trackAddToCartClick(event = {}, eventsHistory) {
if (event.type) {
return event
}
}
trackAddToCartClick.eventType = 'ADD_TO_CART_BUTTON_CLICK';
function trackCartEvents(event = {}, eventsHistory) {
switch(event.type) {
case 'ADD_TO_CART_BUTTON_CLICK':
return event
case 'REMOVE_FROM_CART_CLICK':
break;
default:
}
let tracker = new Tracker([trackAddToCartClick, trackCartEvents])
tracker.on('PRODUCT_CLICK', (event, eventsHistory) =>
console.log(event)
);
tracker.on('*', (event, eventsHistory) =>
console.log(event)
);
tracker.trackEvent({ type: 'ADD_TO_CART_EVENT' })
tracker.trackEvent({ type: 'ADD_TO_CART_EVENT' })
tracker.trackEvent({ type: 'PRODUCT_CLICK' })
Usage with React
components/Product.js
import React from 'react'
import PropTypes from 'prop-types'
const Product = ({ onClick, title, price, currency }) => (
<li
onClick={onClick}
>
{title}
<span> {price} {currency} </span>
</li>
)
Product.propTypes = {
onClick: PropTypes.func.isRequired,
title: PropTypes.bool.isRequired,
price: PropTypes.string.isRequired
currency: PropTypes.string.isRequired
}
export default Product
components/ProductList.js
import React from 'react'
import PropTypes from 'prop-types'
import Product from './Product'
const ProductList = ({ products, trackProductClick }) => (
<ul>
{products.map(product => (
<Product key={product.id} {...product} onClick={() => trackProductClick(product.id, product.price)} />
))}
</ul>
)
ProductList.propTypes = {
products: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
title: PropTypes.string.isRequired,
price: PropTypes.string.isRequired,
currency: PropTypes.string.isRequired,
}).isRequired
).isRequired,
trackProductClick: PropTypes.func.isRequired
}
export default ProductList
Implementing Container Components
Now it's tracking time..
To use withTracking(), you need to define a special function (react-redux-like) called mapTrackingToProps that tells how to pass the trackEvent function to the props.
For example, we need to track product click with Product ID and price, so we need to fire the event on the procut click!
!!!! as we know the trackEvent only accpect the object that describes the Event (type and data if any) !!!!
.../tracking/listeners/cart.js
function trackProductClick(event = {}, eventsHistory) {
if (event.type) {
return event
}
}
trackProductClick.eventType = 'PRODUCT_CLICK';
.../tracking/events/cart.js
function getProductClickEvent(id, price) {
return {
type: 'PRODUCT_CLICK',
data: {
id: id,
price: price
}
}
};
const mapTrackingToProps = trackEvent => {
return {
trackProductClick: (id, price) => {
trackEvent(getProductClickEvent(id, price))
}
}
}
Finally, we create the ProductsList by calling withTracking() and passing our mapTrackingToProps:
import { withTracking } from 'react-tracker'
const ProductsListWithTracking = withTracking(mapDispatchToProps)(ProductsList)
export default ProductsListWithTracking
Let React meet our Tracker
All container components need access to the tracker so they can fire events.
We will use the <Provider> to magically make the tracker available to all container components in the application without passing it explicitly.
You only need to use it once when you render the root component:
index.js
import React from 'react'
import { render } from 'react-dom'
import { TrackerProvider, Tracker } from 'react-tracker'
import { trackProductClick } from './tracking/listeners/cart'
import ProductsList from './components/ProductsList'
let store = new Tracker([trackProductClick ])
render(
<TrackerProvider tracker={store}>
<ProductsList products={someProducts} />
</TrackerProvider>,
document.getElementById('root')
)
Contribution
This project is in its early stages, I'd be very happy if you can help :)
License
MIT