Skip to content

Instantly share code, notes, and snippets.

@aphillipo
Last active September 13, 2022 18:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aphillipo/8b37ac463cc4b370760e2513b6e425b3 to your computer and use it in GitHub Desktop.
Save aphillipo/8b37ac463cc4b370760e2513b6e425b3 to your computer and use it in GitHub Desktop.
Mix Panel Proxy to stop ad blockers while still allowing tracking. Transliterated from https://github.com/mixpanel/flask-tracking-proxy
defmodule HelloWeb.MixPanelProxyController do
use HelloWeb, :controller
@excluded_headers [
"content-encoding",
"content-length",
"transfer-encoding",
"connection",
"access-control-allow-credentials",
"access-control-allow-origin"
]
def js_lib(conn, _) do
handle_api_request(conn, "https://cdn.mxpnl.com/libs/mixpanel-2-latest.js")
end
def js_lib_minified(conn, _) do
handle_api_request(conn, "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js")
end
def api_request(conn, params) do
%{"path" => [path | _]} = params
mixpanel_url =
if path == 'decide', do: "https://decide.mixpanel.com", else: "https://api.mixpanel.com"
# if not using fly.io you'll need to change this
ip = conn |> get_req_header("Fly-Client-IP")
case HTTPoison.request(%HTTPoison.Request{
method: conn.method,
url: mixpanel_url <> "/" <> path,
params: conn.query_params,
headers: %{"x-real-ip" => List.first(ip, "0.0.0.0")},
body: {:form, Map.to_list(conn.body_params)}
}) do
{:ok, %HTTPoison.Response{} = response} ->
conn
|> merge_resp_headers(response.headers)
|> filter_headers(@excluded_headers)
|> send_resp(response.status_code, response.body)
{:error, %HTTPoison.Error{} = error} ->
conn |> put_status(400) |> json(%{"error" => inspect(error)})
end
end
defp handle_api_request(conn, url) do
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{} = response} ->
conn
|> merge_resp_headers(response.headers)
|> filter_headers(@excluded_headers)
|> send_resp(response.status_code, response.body)
{:error, %HTTPoison.Error{}} ->
conn |> send("error")
end
end
defp filter_headers(conn, [first_header | remaining_headers]) do
Plug.Conn.delete_resp_header(conn, first_header)
|> filter_headers(remaining_headers)
end
defp filter_headers(conn, []), do: conn
end
defmodule VeloaWeb.Router do
....
pipeline :mixpanel do
plug(:put_secure_browser_headers)
plug Corsica, origins: "*", allow_credentials: true
end
scope "/mixpanel", VeloaWeb do
pipe_through([:mixpanel])
get("/lib.js", MixPanelProxyController, :js_lib)
get("/lib.min.js", MixPanelProxyController, :js_lib_minified)
get("/*path", MixPanelProxyController, :api_request)
post("/*path", MixPanelProxyController, :api_request)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment