-
-
Save ranic/80459104def4e4bcd73d5c77b817ee43 to your computer and use it in GitHub Desktop.
<html> | |
<head> | |
<title>Mixpanel Tracking Proxy Demo</title> | |
<script type="text/javascript"> | |
/** | |
* Configuration Variables - CHANGE THESE! | |
*/ | |
const MIXPANEL_PROJECT_TOKEN = YOUR_MIXPANEL_PROJECT_TOKEN; // e.g. "67e8bfdec29d84ab2d36ae18c57b8535" | |
const MIXPANEL_PROXY_DOMAIN = YOUR_PROXY_DOMAIN; // e.g. "https://proxy-eoca2pin3q-uc.a.run.app" | |
/** | |
* Set the MIXPANEL_CUSTOM_LIB_URL - No need to change this | |
*/ | |
const MIXPANEL_CUSTOM_LIB_URL = MIXPANEL_PROXY_DOMAIN + "/lib.min.js"; | |
/** | |
* Load the Mixpanel JS library asyncronously via the js snippet | |
*/ | |
(function(f,b){if(!b.__SV){var e,g,i,h;window.mixpanel=b;b._i=[];b.init=function(e,f,c){function g(a,d){var b=d.split(".");2==b.length&&(a=a[b[0]],d=b[1]);a[d]=function(){a.push([d].concat(Array.prototype.slice.call(arguments,0)))}}var a=b;"undefined"!==typeof c?a=b[c]=[]:c="mixpanel";a.people=a.people||[];a.toString=function(a){var d="mixpanel";"mixpanel"!==c&&(d+="."+c);a||(d+=" (stub)");return d};a.people.toString=function(){return a.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms track_with_groups add_group set_group remove_group register register_once alias unregister identify name_tag set_config reset opt_in_tracking opt_out_tracking has_opted_in_tracking has_opted_out_tracking clear_opt_in_out_tracking start_batch_senders people.set people.set_once people.unset people.increment people.append people.union people.track_charge people.clear_charges people.delete_user people.remove".split(" "); | |
for(h=0;h<i.length;h++)g(a,i[h]);var j="set set_once union unset remove delete".split(" ");a.get_group=function(){function b(c){d[c]=function(){call2_args=arguments;call2=[c].concat(Array.prototype.slice.call(call2_args,0));a.push([e,call2])}}for(var d={},e=["get_group"].concat(Array.prototype.slice.call(arguments,0)),c=0;c<j.length;c++)b(j[c]);return d};b._i.push([e,f,c])};b.__SV=1.2;e=f.createElement("script");e.type="text/javascript";e.async=!0;e.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL? | |
MIXPANEL_CUSTOM_LIB_URL:"file:"===f.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";g=f.getElementsByTagName("script")[0];g.parentNode.insertBefore(e,g)}})(document,window.mixpanel||[]); | |
/** | |
* Initialize a Mixpanel instance using your project token and proxy domain | |
*/ | |
mixpanel.init(MIXPANEL_PROJECT_TOKEN, {debug: true, api_host: MIXPANEL_PROXY_DOMAIN}); | |
/** | |
* Track an event when the page is loaded | |
*/ | |
mixpanel.track("[Proxy Demo] Page loaded"); | |
</script> | |
</head> | |
<body> | |
<button onclick="mixpanel.track('[Proxy Demo] Button clicked')">Track event</button> | |
</body> | |
</html> |
If we use track users from a proxy (e.g. "exampleproxy.com), are we able to track users across two separate domains (e.g. "example1.com" , "example2.com") if we are using the same proxy server on both domains?
I'm getting 404 for https://MY_PROXY_DOMAIN/lib.min.js, which also happens if i try directly with https://api.mixpanel.js/lib.min.js.
Am i missing some step?
Hello, thanks for this example, however is there a way to change the endpoint from
/track
to something else to prevent heuristic algorithms from blocking tracking events ?
@mgara as of 2.48.0, you can configure the endpoint /track
to something different. More info here: https://github.com/mixpanel/mixpanel-js/releases/tag/v2.48.0
hello , I used the exact given nginx.conf file, I only changed to a specific port because I am using localhost for running my app also on some other port.
but still got this error.
mixpanel.service.ts:14 Mixpanel error: Bad HTTP status: 0
mixpanel.service.ts:14
POST https://localhost:4999/lib.min.js/track/?verbose=1&ip=1&_=1706010860416 net::ERR_SSL_PROTOCOL_ERROR
here is my nginx.conf file code:
events {}
http {
server {
listen 4999 default backlog=16384;
listen [::]:4999 default backlog=16384;
location /lib.min.js {
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js;
}
location /lib.js {
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass https://cdn.mxpnl.com/libs/mixpanel-2-latest.js;
}
location /decide {
proxy_set_header Host decide.mixpanel.com;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass https://decide.mixpanel.com/decide;
}
location / {
proxy_set_header Host api.mixpanel.com;
proxy_set_header X-Real-IP $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
proxy_pass https://api.mixpanel.com/;
}
}
}
and thats my Angular project code
myid = "ae02abe7863092fe2xxxxxxxxxxxx"
MIXPANEL_CUSTOM_LIB_URL = "https://localhost:4999/lib.min.js";
constructor() {}
init() {
mixpanel.init(this.myid, {
api_host: this.MIXPANEL_CUSTOM_LIB_URL,
debug: true,
track_pageview: true,
});
}
Does anyone have a working example of express/nodejs
proxy setup?
No matter what I try, geocoding doesn't go through even though X-Real-IP
is set (tried first value before comma of x_forwarded_for
as suggested by @StephenHaney above and tried other variations too) plus other headers as per example are set. The proxy logs show all values are set and sent to mixpanel but still no luck
@arthabus Does anyone have a working example of
express/nodejs
proxy setup?No matter what I try, geocoding doesn't go through even though
X-Real-IP
is set (tried first value before comma ofx_forwarded_for
as suggested by @StephenHaney above and tried other variations too) plus other headers as per example are set. The proxy logs show all values are set and sent to mixpanel but still no luck
The proxy we set up is in Deno, but you can probably work your way around it with express/nodejs
as it's fairly similar:
import { serve } from "https://deno.land/std@0.192.0/http/server.ts";
const port = Number(Deno.env.get("PORT") ?? 3009);
serve(
async (request: Request, conn: any) => {
const { pathname } = new URL(request.url);
if (pathname.startsWith("/instrumentation")) {
return await proxyMixpanelCall(request, conn);
}
// ...
},
{ port },
);
async function proxyMixpanelCall(request: Request, conn: any) {
const headers = new Headers(request.headers);
const url = new URL(request.url.replace("/instrumentation", "/track"));
url.port = "";
url.protocol = "https:";
url.host = "api.mixpanel.com";
const remoteAddress = getRemoteAddress(request, conn);
const hostname = getHostname(request, url);
headers.set("Host", "api.mixpanel.com");
headers.set("X-Real-IP", remoteAddress);
headers.set("X-Forwarded-For", remoteAddress);
headers.set("X-Forwarded-Host", hostname);
const proxyRequest = new Request(url.toString(), {
method: request.method,
headers,
body: request.body,
});
try {
return await fetch(proxyRequest);
} catch (e) {
console.log("Failed to proxy call to Mixpanel", e);
return null;
}
}
function getRemoteAddress(request: Request, conn: any) {
return request.headers.get("x-forwarded-for") || conn.remoteAddr?.hostname;
}
function getHostname(request: Request, url: URL) {
return request.headers.get("x-forwarded-host") || url.hostname;
}
@ianlet thanks a lot mate! While I was adopting your solution I realised that I didn't proxy the query params so that was the missing bit. After setting the full mixpanel urls properly with query params it all started to work. Maybe this would help someone in the future.
For future googlers, something before my proxy was changing
$remote_addr
to be one hop away client's actual IPs. Often only a few digits different, so hard to notice. For some reason, geolocation wasn't working with these hop IPs.Instead of using
$remote_addr
, I switched to using the first IP from$http_x_forwarded_for
as myX-Real-IP
header that I send to MixPanel. After this, geolocation started working.Here's the nginx snippet to grab the first value from
$http_x_forwarded_for
and then later: