Uncategorized

Community Tip: Server-side Identity Management

This Community Tip details how to maintain a user’s identity both in purely server-side as well as hybrid server-side and client-side implementations. Using these instructions, you can ensure user identity remains consistent across all server-side updates.

Recently we published a Community Tip on maintaining user identity which highlights the nuances of identity management when users log in from multiple client-side devices. This post provides great insight and strategies to ensure the identity of a user remains consistent through the interactions made with your site or app.

While implementations involving server-side updates follow the same basic principles, in this post we dive deeper into how identity can be maintained from the server-side perspective. Below we outline the two possible scenarios for your implementation: sending data only from the server, or from both the server and the client.

Server-side Only Implementations

Assuming all events originate from the server (an example could be tracking requests made to an API), the procedure for maintaining identity is straightforward. Each event should have a unique identifier (known in Mixpanel as the Distinct ID) to tell users apart, meaning from a user’s first interaction you will need to generate your own ID and send it along with each event.

When a visitor is in an anonymous state, you will want to generate a unique ID on the server and keep it consistent for a user (sending it with each event). If your workflow supports identifying the user (signing up or logging in), you can then choose to either create an alias (PHP / Python / Ruby) for that anonymous ID, or continue to identify the user by the previously existing ID on your server.

Overall, a purely server-side implementation prevents against major complications as it’s up to your sever alone to determine the identity of a user at any given time.

Hybrid Server and Client Implementations

Some events are inherently related to client-side interactions (like clicking a button), and some should normally reside on the server (like storing a transaction). Arguably there can be overlap with certain type of events, meaning ultimately you will need to decide where an event will be recorded depending on your specific use case.

For the purposes of walking through an example of a hybrid server and client implementation, let’s assume we have a common sign up workflow on a website (JavaScript and PHP). Part of this workflow is loading the sign up form on the client side and another the actual sign up itself after which we store the user on our server.

Both events could be triggered server-side, but the former is traditionally located on the client given that it can easily detect when a page has finished loading. Triggering the sign up event on the server is useful as you can make sure it’s only triggered once upon success, you have the newly created ID readily available (for aliasing purposes), and you don’t have to cope with client issues such as a user loading the confirmation page several times.

Since the event collection starts on the client side, we want to send the user’s automatically generated distinct ID from the client side to the server for consistency.

Here’s a simple sign up form in JavaScript:

<form id="myForm" action="createUser.php" method="POST">
    <input type="hidden" name="distinct_id" value="" />
    <label for="name">Name:</label> <input type="text" id="name" name="name" /><br/>
    <label for="email">Email:</label> <input type="email" name="email" id="email" /><br/>
    <input type="submit" value="Submit" />
</form>

This sign up form only has two inputs, name and email, but we also include a hidden field which will carry the distinct ID information to the server. Before the form sends the information to the server, we will want to populate the value of that field with the current distinct ID used in previous events:

$(function(){
    var myForm = $("#myForm");
    //track the page load
    mixpanel.track("Page load", {"Page": "Signup Form"});

    /*
    Listen to the form being submitted;
    before it sends the request, the current distinct ID will be added
    */

    myForm.submit(function(event){
        var hiddenInput = myForm.find("input[name='distinct_id']");
        hiddenInput[0].value = mixpanel.get_distinct_id();
    });
});

The distinct ID is stored in the cookie by default with the Mixpanel JavaScript library, but passing it through the form simplifies this process as there is no need to parse the cookie and then send along to the server.

Once the form is submitted, the server will receive a payload with the information the user inputted, plus our additional field containing their distinct ID. With the information on the server, and once the proper form validation is made, all we need to do is track the event and create an alias of the new ID on our server for our user to that which was automatically assigned on the client.

After an alias has been created (this can be done on the client or server side), our server does not need to keep track of the original distinct ID anymore as we can use our own generated ID both on the server and client side. Having said that, sending the alias creation request to Mixpanel is an operation which can take some time to resolve, so to avoid any race conditions you should send any event and profile updates with the original distinct ID for 2 seconds after an alias is created.

Below, you will see sample PHP code for establishing this alias and sending events to Mixpanel with a consistent distinct ID:

// imaginary user class that takes the form submission
// information and stores it in the data base
require 'users.php';
$u = new UserClass();
//importing Mixpanel
require 'vendor/autoload.php';
$mp = Mixpanel::getInstance("MIXPANEL_PROJECT_TOKEN");
$result = registerUser(array(
    'name' => $_POST['name'],
    'email' => $_POST['email']
));
// the registerUser function will return
// 0 if there was an error or an ID for the user created
if($result > 0){
    // the user was correctly saved
    // we can trigger the event and create the alias
    // we send the events with the original distinct_id to prevent
    // any racing conditions related to using the alias before
    // it has been created
    $current_distinct_id = $_POST['distinct_id'];
    $mp->identify($current_distinct_id);
    $mp->track("Signup completed");
    //create the alias
    $mp->createAlias($current_distinct_id, $result);
}
//sending back a JSON response with the result
echo json_encode(array('result'=>$result));
?>

The step by step guide for what is happening in the above code is self contained within the code comments, but besides the actions taken it’s important to review the overall concept:

  • Events were tracked on the client with a distinct ID
  • The client sent information to the server along with the current distinct ID
  • The server processed the information, created an alias with a new ID, and sent it back to the client

As mentioned previously, since this is a web environment, PHP could have read the cookie contained in the request (as the distinct ID is stored in the cookie by default), but this approach is not taken in this case to illustrate purposely sending the said ID. Reading the cookie is often not an option as the client could be a native mobile app, or you might be using local storage instead of cookies so the best practice is to use Mixpanel methods to do the work for you.

When you have a hybrid server and client side implementation, it’s a two-way street where each component should communicate between one another in order to maintain identity.

Any doubts or questions as to how you can maintain server-side identity? Reach out to support@mixpanel.com to speak to someone smart, quickly.

Get the latest from Mixpanel
This field is required.