eealeivan/mixpanel-csharp

Setting a Person's IP address fails unless accompanied with other properties

yaronguez opened this issue · 2 comments

I'm trying to update a person's profile with their IP address but find that MixPanel does not recognize the update unless another property is included. This behavior does not happen when using the JavaScript library.

For example, the following has no effect on the user's profile:

_mixPanelClient.PeopleSet(userName, new Dictionary<string, object>
{
    { MixpanelProperty.Ip, "some.ip.address"  }
});

Whereas the following WILL update the user's location MixPanel (and create a new foo = bar property)

_mixPanelClient.PeopleSet(userName, new Dictionary<string, object>
{
    { MixpanelProperty.Ip, "some.ip.address"  },
    { "foo", "bar"}
});

Whereas with the Javascript library, running mixpanel.people.set("ip", "some.ip.address") will update the user's profile accordingly.

IP property is not very clear in Mixpanel. I made some research and that's what I found.

When you go to user profile in Mixpanel there are two different IP's:

  1. Location that is shown in header under user name and email (shown not as IP but geographical location);
  2. Ip - special property in right panel.

Location can be set in two ways.

  1. By setting $ip property in message root. This is what mixpanel-csharp currently does;
  2. By setting ip query string parameter.

If $ip isn't provided (and ip=0 isn't provided as a URL parameter), Mixpanel will use the IP address of the request. Mixpanel uses an IP address to guess at the geographic location of users. If $ip is set to "0", Mixpanel will ignore IP information.

JS library by default sets query string parameter ip=1 and it seems that there is no way to change location. mixpanel-csharp doesn't set this query string, but if $ip is not set, then Mixpanel considers this as 1.

Ip can be set by setting $ip property in $set object. mixpanel-csharp doesn't support that currently.

Example:

{
  "$token": "token",
  "$distinct_id": "1",
  "$ip": "This will set 'Location'",
  "$set": {    
    "$ip": "This will set 'Ip' property"
  }
}

To be able to fix that I'm thinking about having two properties:

  1. MixpanelProperty.LocationIp - will behave like current Ip;
  2. MixpanelProperty.Ip - will be used in $set object.

Thanks for the reply, Aleksandr!
I'm not interested in tracking IP specifically. I'm only interested in the user's location. I'd like to set the user's location via their IP address when they first register through our API and then never change it thereafter since I can't be sure that other API calls we're tracking are coming from the physical user.

This is how I'm trying to accomplish this: When when a user registers, I call:

messages.Add(_mixPanelClient.GetPeopleSetMessage(distinctId, new Dictionary<string, object>
{
    { MixpanelProperty.Email, user.Email },
    {MixpanelProperty.Ip, HttpContext.Current?.Request.UserHostAddress }
}));
await _mixPanelClient.SendAsync(messages);  

In all my other GetPeopleSetMessag calls I'm including the entry {MixpanelProperty.Ip, 0 } so that it doesn't overwrite this initial location, for example:

messages.Add(_mixPanelClient.GetPeopleSetMessage(user.UserName, new Dictionary<string, object>
{
    {MixpanelProperty.Ip, 0 },
    {"SomeOtherProperty", "SomeOtherValue" },
    {"AnotherProperty", "AnotherValue" }
}));
await _mixPanelClient.SendAsync(messages);  

Meanwhile, I set a super property with the user's IP address to track the location of individual events:

_mixPanelClient.SetSuperProperties(new Dictionary<string, object> { { MixpanelProperty.Ip, HttpContext.Current?.Request.UserHostAddress } });

This appears to be working properly. Is this the correct approach given your description above?

Thanks so much for your help!