mixpanel / tracking-proxy

One-click configuration to proxy tracking requests to Mixpanel's API
63 stars 117 forks source link

feedback: Cloudflare worker proxy #23

Open BrentOnRails opened 2 months ago

BrentOnRails commented 2 months ago

If you're interested, I ended up implementing this via Cloudflare workers using this nginx config as inspiration.

1) Create a worker and add the javascript

export default {
    async fetch(request) {
        return handleRequest(request)
    }
}

async function handleRequest(request) {
    const url = new URL(request.url)
    let targetUrl

    // Determine the target URL based on the request path
    switch (true) {
        case url.pathname === '/lib.min.js':
            targetUrl = 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js';
            break;
        case url.pathname === '/lib.js':
            targetUrl = 'https://cdn.mxpnl.com/libs/mixpanel-2-latest.js';
            break;
        case url.pathname.startsWith('/decide'):
            targetUrl = 'https://decide.mixpanel.com' + url.pathname.slice('/decide'.length);
            break;
        default:
            targetUrl = 'https://api.mixpanel.com' + url.pathname;
            break;
    }

    // Create a new request with the target URL and the original request's settings
    const modifiedRequest = new Request(targetUrl, {
        method: request.method,
        headers: request.headers,
        body: request.body,
        redirect: request.redirect,
    })

    // Add necessary headers to mimic the Nginx configuration
    modifiedRequest.headers.set('X-Real-IP', request.headers.get('cf-connecting-ip'))
    modifiedRequest.headers.set('X-Forwarded-For', request.headers.get('cf-connecting-ip'))
    modifiedRequest.headers.set('X-Forwarded-Host', url.hostname)

    // Fetch the modified request
    const response = await fetch(modifiedRequest)

    return response
}

2) set the route you want in settings -> triggers -> custom domains

Cloudflare workers also support the one button deployment badges

kutanov commented 1 month ago

Thank you! I added search parameters to enable mixpanel geolocation enrichment

var worker_default = {
  async fetch(request) {
    return handleRequest(request);
  }
};
async function handleRequest(request) {
  const url = new URL(request.url);
  const search = url.search;
  let targetUrl;
  switch (true) {
    case url.pathname === "/__mix/lib.min.js":
      targetUrl = "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";
      break;
    case url.pathname === "/__mix/lib.js":
      targetUrl = "https://cdn.mxpnl.com/libs/mixpanel-2-latest.js";
      break;
    case url.pathname.startsWith("/__mix/decide"):
      targetUrl = "https://decide.mixpanel.com" + url.pathname.replace("/__mix/decide", '/');
      console.log(targetUrl);
      break;
    default:
      targetUrl = "https://api.mixpanel.com" + url.pathname.replace('/__mix/', '/');
      break;
  }
  const modifiedRequest = new Request(targetUrl+search, {
    method: request.method,
    headers: request.headers,
    body: request.body,
    redirect: request.redirect
  });
  modifiedRequest.headers.set("X-Real-IP", request.headers.get("cf-connecting-ip"));
  modifiedRequest.headers.set("X-Forwarded-For", request.headers.get("cf-connecting-ip"));
  modifiedRequest.headers.set("X-Forwarded-Host", url.hostname);
  const response = await fetch(modifiedRequest);
  return response;
}
export {
  worker_default as default
};