Tracking Geolocation with Server-Side Implementation

Mixpanel’s client-side libraries automatically send certain properties, such as location data. However, it is still possible to store users’ location data when you send server-side updates.

Geolocation data ($city, $region, mp_country_code) is set from the IP address on the incoming request when data connects to Mixpanel’s servers.

As all server-side calls originate from the same IP, such as the IP of your server, it can have the unintended effect of setting the location of all of your users to the location of your datacenter.

Geolocation and Events

Here’s an example event call to our REST API that sends an event "Level Complete" with a single property "Level Number".

The REST API won’t perform any geolocation by default. It assumes you’re sending these calls server-side, although you can force it when you send in a property called “ip.”

The request uses the value sent with the “ip” parameter for geolocation, so this event appears to have come from New York.

"event": "Level Complete",
"properties": {
"Level Number": 9,
"distinct_id": "13793",
"token": "e3bc4100330c35722740fb8c6f5abddc",
"time": 1409259110,
"ip": ""

Geolocation and People Profile Updates

People profile updates present more issues with geolocation because they are often batch-updated server side or over the REST API. But calls to engage assume that you want to use the IP address of the request if no IP property is given.

As a result, each user appears to be located wherever the server that sends the requests is located. You can override this behavior by including ip=0 as a URL parameter, for example:

This action forces Mixpanel to ignore the IP on the request, leaving the geolocation information untouched so that it reflects whatever was previously set with another library, instead of overwriting it.

Pass Your Own IP Address (Javascript/HTTP)

If you want to pass in your own IP address similar to the way you can with track, leave out the URL parameter ip= and add a property called $ip to the message payload.

"$token": "e3bc4100330c35722740fb8c6f5abddc",
"$distinct_id": "13793",
"$ip": "",
"$set": {
"Address": "1313 Mockingbird Lane"

Notice that you need to set $ip outside of the $set dictionary. This action overwrites the geographic data on the profile with distinct_id = 13793 with New York, NY.

Pass Your Own IP Address (Java)

If you want to pass in your own IP address, you can add a property called $ip to the message payload.

new MessageBuilder(PROJECT_TOKEN);

JSONObject props = new JSONObject();

props.put("Plan", "Premium");



JSONObject update = messageBuilder.set("13793", props);

MixpanelAPI mixpanel = new MixpanelAPI();


Notice that you set the $ip property to set the ip address of the user. This prevents all events being ingested with the IP address of your server. When you send people updates, $ip must be included as a modifier parameter outside the properties dictionary. Pass the $ip property in a people.set() call in a separate dictionary as the third argument to update City, Region, or Country properties. 

Set the $ignore_time property to not update the $last_seen property with the time when Mixpanel ingested the data. Set the $ip property to use user data location data in Mixpanel because Java does not capture location by default. 

Pass Your Own IP Address (Node.js)

If you want to pass your own IP address similar to the way you can with track, leave out the ip= URL parameter, and add a property called ip to the message payload:

mixpanel.people.set(req.session.user._id, { 
  ip: req.param('ip') 

Force the IP (Ruby)

All Mixpanel server-side libraries have parameters that allow you to force the IP behavior that you want.

The following are examples in a Ruby implementation:

The general format of set() could look like:

def set(distinct_id, properties, ip=nil, optional_params={})

Using the IP in the property for Geo-location:

tracker.people.set('Drew', {'$first_name' => 'Drew'}, '')

Not using Geo-locate:

tracker.people.set('Drew', {'$first_name' => 'Drew'}, '0')
tracker.people.set('Drew', {'$first_name' => 'Drew'}, 0)

Geo-locates from the IP on the request:

tracker.people.set('Drew', {'$first_name' => 'Drew'}, nil)

Does not Geo-locate or update $last_seen” 

tracker.people.set('Drew', {'$first_name' => 'Drew'}, 0, {'$ignore_time' => 'true'}
Is this article helpful?



Article is closed for comments.