DEV Community

Gosha Arinich
Gosha Arinich

Posted on • Originally published at goshakkk.name on

2

Analytics on easy mode with Redux-Saga

This post was originally published on goshakkk.name

Tracking how your users actually use your application can be powerful.

And to do that, you could put the window.ga(...) calls all around: inside action creators or your components.

But does that approach strike you as beautiful, in any way?

class SignUpForm extends Component {
  handleSubmit = () => {
    // fire a redux action
    this.props.doSignUp(data).then(() => {
      window.ga('track', 'CompleteRegistration');
    });
  };
}

class AddTodoForm extends Component {
  handleSubmit = () => {
    // fire a redux action
    this.props.createTodo(data).then(() => {
      window.ga('track', 'CreateTodo');
    });
  };
}
Enter fullscreen mode Exit fullscreen mode

You can see where it’s going.

Can you do better?

With Redux-saga, you can. You can place all analytics-related behavior (or most of it, anyway) in a separate file. Which would “listen for certain Redux actions, and automatically track to your analytics service.

But first, what’s Redux-saga about? In its simplest form, a saga, the unif of Redux-saga, is a function like this:

function* aSaga() {
  while (true) {
    const action = yield take('ACTION_NAME');
    // do something
  }
}
Enter fullscreen mode Exit fullscreen mode

It waits for a certain action to happen, then does something — whetever you want. After that, it would wait for another action to occur, and the cycle would repeat.

You could make a lot more complicated sagas, but these are a great start!

(Now, if you are wondering what this function* and yield are — these have to do with ES6 generator functions. I have a blog post explaining them in more detail.)

A more practical example would be:

// analytics-sagas.js

function* registrationAnalytics() {
  while (true) {
    yield take('USER_SIGNED_UP');
    window.ga('track', 'CompleteRegistration');
  }
  }

function* todoAnalytics() {
  while (true) {
    yield take('ADD_TODO');
    window.ga('track', 'CreateTodo');
  }
  }

sagaMiddleware.run(registrationAnalytics);
sagaMiddleware.run(todoAnalytics);

export [
  registrationAnalytics,
  todoAnalytics,
];

// when creating redux store

import analyticsSagas from './analytics-sagas.js';

// ...

analyticsSagas.forEach(saga => sagaMiddleware.run(saga));
Enter fullscreen mode Exit fullscreen mode

Look at this code.

The entire functionality of analytics is now contained in one single file.

And instead of making calls to analytics in our components, we can “feed from Redux actions as they happen.

Considerations

Since sagas can only respond to Redux actions, there still might be places in your app where you would inline analytics calls right inside components. However, even so, you’d be still better off than with inlining everything.

Other uses for sagas

References


If you like what you see here, subscribe on my blog to make sure you don't miss out on my next posts about React and Redux.

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

Instrument, monitor, fix: a hands-on debugging session

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️