Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Jepser Bernardino
Jepser Bernardino

Posted on • Edited on

     

Hello Treacker, a tracking library for React

TL;DR:

I built a small (1.5kb) and performant event tracking library, that lets you connect with any tracking provider (GA, MixPanel, etc) with its simple API.

Why another tracking library

Tracking solutions likeReact tracker orReact tracking solve the tracking the challenge coming for a perspective that data is present at the moment the tracking event is being triggered, meaning that the data needed to track an event is available from time 0.

Which in reality it's not. Let's see the following example:

constComponent=({userId,roomId})=>{consttracking=useTracking()useEffect(()=>{tracking.trackEvent({action:'invite_sent',userId,roomId})},[])// the rest of my component}
Enter fullscreen modeExit fullscreen mode

But, what if because of the architecture of the application, the asynchronous nature of nowadays applications (or any other reason)theuserId orroomId values are not available when mounting the component, the tracking event won't report the correct data.

Having a condition could fix the problem:

constComponent=({userId,roomId})=>{consttracking=useTracking()useEffect(()=>{if(!userId||!roomId)returntracking.trackEvent({action:'invite_sent',userId,roomId})},[userId,roomId])// the rest of my component}
Enter fullscreen modeExit fullscreen mode

But I will need to do this do it over and over across the application, this starts to be unmaintainable and too verbose. Instead, what if there could be a way to let the "tracking system" manage that for us, what if the data integrity is part of the responsibilities of this "tracking system".

The proposal

I want to create a tool that:

  • Works with vanilla JS and React is just an abstraction, so it's not dependant of React architecture constraints.
  • Its responsibility is to ensure the tracking data integrity
  • Provides a declarative interface
  • It is agnostic of the transport service is used on the project to track the events
  • Has a simple, yet powerful interface

Say hello to Treacker

(Tracking + React) = Treacker 🤯

Treacker takes the following assumptions on the application architecture:

  • The part of the code in which the "tracking provider" is declared knows about the base data that will need to be tracked (ex. userId, userRole, appVersion), let's say, the global/high-level data

Said that let's see how it works:

  1. Declare aTrackingProvider
  2. Everything you want to track should be inside the Provider tree
  3. Access the provider either usingTrackingContext oruseTracking hook

Demo

Example

  • I have will requestgetRooms and received as a listrooms as props, in which I will track the mounting of each room on the list
  • I have a component that will show info on a user calledUserComponent that will be shown after doing a request to the server in which I will track when mounting
import{useState,useEffect}from'react'import{TrackingProvider}from'treacker'importUserComponentfrom'./user-component'importRoomfrom'./room'constINITIAL_PARAMS={locale:'en',app_version:1}consthandleOnTrackingEvent=event=>{// do stuff when the event has been fired.// like reporting to Google Analytics or Mixpanel// signature { eventName, params, timestamp }}constLayout=({getUser,getRoom,rooms})=>{const[ready,setReady]=useState(false)const[params,setParams]=useState(INITIAL_PARAMS)useEffect(()=>{getUser().then((user)=>{// update the parameters for the providersetParams(state=>({...state,userRole:user.role,userId:user.id,})setReady(true)})getRoom()},[])return(<TrackingProviderparams={params}onTrackingEvent={handleOnTrackingEvent}isReady={ready}><UserComponent{...user}/>{rooms.map(room=><Room{...room}/>)}</TrackingProvider>)}
Enter fullscreen modeExit fullscreen mode

TheUserComponent:

import{useEffect}from'react'import{useTracking}from'treacker'constUserComponent=()=>{consttracking=useTracking()useEffect(()=>{tracking.track('user-component.loaded')},[])return(// ... the component implementation)}
Enter fullscreen modeExit fullscreen mode

Then the room component:

import{useEffect}from'react'import{useTracking}from'treacker'constRoom=({roomId})=>{consttracking=useTracking()useEffect(()=>{tracking.track('room.loaded',{roomId})},[])return(// ... the component implementation)}
Enter fullscreen modeExit fullscreen mode

So what's happening here?

  • TrackingProvider has 3 main props:
  • onTrackingEvent, which will be invoked each time there is a tracking event
  • params, this is going to be the global parameters that will be sent with each event
  • isReady is the flag that will let know when it's "safe" to dispatch the events

For more info on how the event signature looks like,check the docs.

Even if the data is not ready, for example likeUserComponent that mounts before fetching the userData, the events stay in a queue and are dispatched only after knowing that is safe by theisReady flag onTrackingProvider.

More about the interface

withTracking

The library exposes also aHOCwithTracking which is useful when the component is not part of theTrackingProvider tree.

registering listeners

In case you need to register more event listeners to the trackingProvider, it's possible usingregisterListener.

Final words

I found the approach to be useful in my use case and that's why I thought to share it, hopefully it will be useful for you too!

Check the docs for more details, or the demo incodesandbox.

Top comments(6)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
mati365 profile image
Mateusz Bagiński
  • Joined

Cool but why? Google Analytics has already super easy to use API, advanced dashboards

CollapseExpand
 
jepser profile image
Jepser Bernardino
Code poet from the land of coffee and eternal spring.
  • Location
    Barcelona
  • Work
    Fullstack Engineer at Maze.design
  • Joined

It's not excluding GA, it plays with it. Tracking libraries, like this one, helps you to create an abstraction of GA or Mixpanel, or NewRelic so your code doesn't depend on their specific API.

By using Treacker you can move the "event reporting" to a function that only knows when it's being called with certain signature. Also, let's say that you change from GA to MixPanel or Segment, then, with this, it will be easier because there are not implementation details on your code.

CollapseExpand
 
sureisfun profile image
Barry Melton
Web/app/mobile dev, currently focusing on really boring things like technical SEO
  • Location
    Annapolis, MD
  • Work
    Funemployed ex-CTO at a small startup
  • Joined

I was having some problems with my event tracking and was about to rewrite everything when I saw this, so I cut over everything to it. So far, it actually looks really nice and effective. In my handleOnTrackingEvent, I'm just sending everything to an abstract 'track' which then calls trackGA or trackMixpanel for all the events so that I can do some extra parsing.

The only thing I don't see an obvious way to handle is how to do tracking from a redux action creator. My best guess is to just use the vanilla example and adapt it, but if you could provide any guidance or examples, it would be dearly appreciated before I get too far down the rabbit hole.

CollapseExpand
 
jkhaui profile image
Jordy Lee
Melbourne-based full-stack JavaScript developer.Currently leading the web team for Centr.com by Chris Hemsworth & emilyskyefit.com
  • Location
    Melbourne
  • Education
    Swinburne University of Technology
  • Work
    Software Developer at Loup.
  • Joined

Wow talk about coincidence! I was just looking for a React-based tracking library and was wondering why there isn't much other than the NY Times' solution.
Looks awesome, can't wait to try it out

CollapseExpand
 
sathaan profile image
sathaan
  • Joined
• Edited on• Edited

How to use this tracker in class component. it support only functional component.

CollapseExpand
 
jepser profile image
Jepser Bernardino
Code poet from the land of coffee and eternal spring.
  • Location
    Barcelona
  • Work
    Fullstack Engineer at Maze.design
  • Joined

Hi@sathaan! the version 1.0.2 exposes the TrackingContext and TrackingProvider in case you want to use it with a class component or a function components without hooks:github.com/Badiapp/treacker#using-...

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Code poet from the land of coffee and eternal spring.
  • Location
    Barcelona
  • Work
    Fullstack Engineer at Maze.design
  • Joined

More fromJepser Bernardino

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp