Company Profiles

Proper user behavior analytics (UBA) requires a mechanism for identifying and tracking users accessing an app. While this sounds simple in theory since you could just append a user id to some logs, it’s actually quite challenging in practice if you want an accurate representation of the customer journey.

Overview of user tracking

The challenge stitching together a customer journey

Most platform-focused companies have a variety of different products. Some products are API-based applications that are accessed by customers programmatically whereas other products are web-based applications that a customer logs into with their browser and uses interactively. It’s critical to stitch together a holistic customer journey so you can understand funnel metrics like initial sign up to first API call even if across both your API and web apps.

Funnel Analysis Overview

Yet, each of these products may have different ways to identify and authenticate users which create multiple challenges. An API may require adding a bearer token whereas a website may require a user to log in via an OAuth flow and store a session cookie. In addition, not all users have identifying information. For example, you may have anonymous visitors who browser your website before they signed up. These visitors don’t even have a user id generated yet. What if the same anonymous visitor browses your website from multiple devices? A naive user tracking implementation would double count that person twice reducing the integrity of your metrics.

How Moesif solves this

The recommended way to set up Moesif is with two integration points:

  1. A server integration to monitor API calls.
  2. A client integration to track users and their web activity.

A complete implementation is shown in the below diagram.

Diagram of Moesif Moesif client and server monitoring architecture

Behind the scenes, the Moesif platform leverages a variety of tricks to accurately stitch together the journey of each customer. This mechanism includes user aliasing, anonymous ids, and merging users. Most of this is handled automatically by Moesif, but this article goes into detail on what you need and how it works.

User Id

A common user id is the mechanism Moesif associates traffic from different platforms to the same customer. You should ensure both your server integration and client integrations call the identifyUser method with the same id. Different ids will not work.

Client integration

Identifying users

Once you know the user id of a customer, call identifyUser() with the user id. This should be done as soon as possible such as when a user logs into your app. Otherwise, tracking data can be lost if the customer clears their browser’s cookies and local storage before being identified with Moesif.

An example of how to do this is below:

<script src="//unpkg.com/moesif-browser-js@v1/moesif.min.js"></script>
<script type="text/javascript">
  moesif.init({
    applicationId: "Your Moesif Application Id",
  });

  // Identify the user with Moesif such as when user logs in
  moesif.identifyUser("12345");
</script>

Anonymous users

When a new visitor browses your website which has a client integration like moesif-browser-js installed, Moesif generates an anonymous user id and stores in the user’s device. This anonymous id is persisted both into localStorage and replicated to a cookie for redundancy so that if the user clears local storage or visits a different subdomain (like from docs.acmeinc.com to acmeinc.com), there is still a cookie to fall back to and the user can be accurately attributed.

Anonymous users makes it possible to correctly track unique users and stitch together the user journey before and after they signed into your app. Moesif uses two different ids to accomplish this:

Name Description
User Id The internal User Id assigned by Moesif. This may be either a generated Anonymous Id or can be your Identified User Id or Anonymous Id.
Identified User Id The Identified User Id set by you by the identifyUser function. When no Identified User Id is set, the user is anonymous and has not been identified.

You should call moesif.reset() when a user logs out of your application to ensure a new anonymousId is generated. Otherwise, new activity may get associated with an old user session.

User merging

Moesif will automatically merge users if they are identified as the same person. This can happen if an existing user (that was previously tracked in Moesif) starts browsing your app on a new device. A new anonymous profile is created as soon as the user starts browsing anonymously from their new device. Once the user logs in (thus identifyUser() is called), Moesif will merge the newly created anonymous profile with the previously created user profile. You will see only one user in Moesif.

The below table describes different scenarios on how Moesif handles user creation and merging:

Example Scenario How Moesif handles
No User Id identified All events will be associated with an anonymous user profile. Identified User Id is null. User Id is set to a generated Anonymous Id.
User Id is identified after anonymous events Events are associated with an anonymous user profile. Initially Identified User Id is null. Once the user is identified, both User Id and Identified User Id are set to the actual user id.
Same User Id on multiple devices, with no anonymous events Events will be initially associated to two different anonymous profiles. Once the user is identified, both profiles will be merged into a single user profile. User Id and Identified User Id are set to the actual user id.
Multiple User Ids on the same device Two profiles will be created, one for each user id. No merging will occur. Ensure moesif.reset() is called when a user logs out. Otherwise, events may get associated to an old user session.
Multiple User Ids on the same device, with anonymous events Ensure moesif.reset() is called when a user logs out. Otherwise, events may get associated to an old user session.

Server integration

Identifying users

You’ll need to ensure your server integration correctly identifies users so that API traffic is associated to each customer. This is done by implementing the identifyUser hook with your custom logic that returns the user id. You have access to the request context so you can read a particular header like X-User-Id, use an internal variable such as by authentication middleware, or other arbitrary code.

An example is below for Node.js, but you should review the identify user section for your respective server integration.

const moesifMiddleware = moesif({
  applicationId: 'Your Moesif Application Id',

  // Return thr user id set by the auth middleware. 
  identifyUser: function (req, res) {
    return req.user ? req.user.id : undefined;
  },
});

app.use(moesifMiddleware);

Many of the API gateway plugins and SDKs have a default identifyUser function out of the box based on the conventions for that framework. For example, the Kong plugin reads the value set in x-consumer-custom-id, the AWS API gateway reads the value principalId and cognitoIdentityId, and moesif-nodejs uses the value set in req.user.id

Anonymous Ids

Unlike the client integration, the server integration doesn’t have the notion of anonymous user ids. This is because API traffic is usually authenticated traffic by definition.

Linking users to companies

In addition to tracking users, you can also track usage at the company-level. This is helpful if your business primarily sells to other businesses (B2B).
Company tracking works by assigning a user to a company (i.e. a group of users) and can be done one of two ways:

  1. Implement the identifyCompany option in server integration such as to read a header like X-Company-Id
  2. Set a company_id when updating a user such as by calling identifyUser() via moesif-browser-js.

Option 2 can be handy if you don’t have company info readily available in the API calls themselves. Moesif will associate the user to a company profile. Once done, all future traffic made from that user will be tracked also by the linked company.

Logging out

If you are using moesif-browser-js, call moesif.reset() when a user logs out of your web app. This ensures a new anonymous id is generated and ensuring different sessions are not mixed up and super important for testing

Updated: