Quick Overview
Mixpanel has great documentation for setting up your project in many different languages, including JavaScript. They also provide docs and examples for implenting tracking with a proxy. Setting up Mixpanel through a proxy is useful to bypass ad and tracking blockers, and is a nice way to keep all client requests through your domain.
I didn't see any great resources out there for setting up Mixpanel specifically in Next.js using their built-in Rewrites feature to accomplish the same goal as setting up a proxy. Using rewrites, I was able to keep all Mixpanel requests going through the same domain as my website/app, and didn't need to deal with configuring Nginx myself (I'm hosting on Vercel, so I don't normally have to touch webserver config).
This is how I implemented that setup.
Step 1: Install Mixpanel's JS SDK
We are going to use Mixpanel's JS SDK mixpanel-browser
. You can install it with npm/yarn as follows.
# npm
npm install --save mixpanel-browser
# yarn
yarn add mixpanel-browser
If you're using TypeScript, you can also install @types/mixpanel-browser
to have typings.
Step 2: Create Mixpanel wrapper function
Note - This post is to explain the setup for using Next rewrites. I used this article as a guide for creating a basic Mixpanel wrapper function.
Create a file called mixpanel.{ts|js}
wherever it makes sense in your project. We will be defining an object which will be imported and used anywhere you plan to implement Mixpanel tracking.
// Remove { Dict, Query } if not using TypeScript
import mixpanel, { Dict, Query } from "mixpanel-browser";
const isProd = process.env.NODE_ENV === "production";
mixpanel.init("YOUR_MIXPANEL_TOKEN", {
// Use your project's URL, adding a slug for all Mixpanel requests
api_host: "https://yourdomain.com/mp",
});
export const Mixpanel = {
identify: (id: string) => {
mixpanel.identify(id);
},
alias: (id: string) => {
mixpanel.alias(id);
},
track: (name: string, props?: Dict) => {
mixpanel.track(name, props);
},
track_links: (query: Query, name: string) => {
mixpanel.track_links(query, name, {
referrer: document.referrer,
});
},
people: {
set: (props: Dict) => {
mixpanel.people.set(props);
},
},
};
First we import the mixpanel-browser
library.
When in initialize it, we specify our own api_host
. This is where we tell Mixpanel to use our URL instead of theirs. This url should be the same as your Next.js project's URL, with a specific slug which will be dedicated to only Mixpanel requests (e.g. /mp
). You can make this whatever you want it to be, so long as it is not used anywhere else in your project.
Step 3: Add rewrites
Now we need to tell Next to handle the rewrites for the URL we just provided to Mixpanel.
In next.config.js
add the following (yours might have additional configs already, the rewrites is what we care about).
/** @type {import('next').NextConfig} */
module.exports = {
async rewrites() {
return [
{
source: "/mp/lib.min.js",
destination: "https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js",
},
{
source: "/mp/lib.js",
destination: "https://cdn.mxpnl.com/libs/mixpanel-2-latest.js",
},
{
source: "/mp/decide",
destination: "https://decide.mixpanel.com/decide",
},
{
source: "/mp/:slug",
// use "api-eu.mixpanel.com" if you need to use EU servers
destination: "https://api.mixpanel.com/:slug",
},
];
},
};
This tells Next, when a request is made to each of these endpoints, it will perform a rewrite to the destination
URL. You can find more details about these rewrites in Next's documentation.
Step 4: Track things
Now you can use your Mixpanel object throughout your Next project. Import it using import { Mixpanel } from './mixpanel';
Then use it to track events, link clicks, and anything else useful. (These are just examples, not indicative of useful events to track).
import { useEffect } from "react";
import Link from "next/link";
import { Mixpanel } from "./path/to/mixpanel";
const PageName = () => {
useEffect(() => {
Mixpanel.track("Loaded PageName");
Mixpanel.track_links("#nav a", "Nav link clicked");
}, []);
const handleButtonClick = () => {
Mixpanel.track("Button clicked");
alert("Button clicked!");
};
return (
<div className="container">
<div id="nav">
<Link href="/dashboard">
<a>Home</a>
</Link>
<Link href="/about">
<a>About</a>
</Link>
<Link href="/pricing">
<a>Pricing</a>
</Link>
</div>
<button onClick={handleButtonClick}>Click me!</button>
</div>
);
};
export default PageName;
Wrapping up
There you have it. All requests for Mixpanel should now be going through your app's domain, effectively working as a proxy using Next's built-in Rewrites capabilities.
Let me know if this worked for you, or if you have suggestions for a better approach in the comments!
Top comments (3)
I tried to implement this, but found that, tracking no longer provides the geolocation of the event. I assume this is because of the proxy, where the IP of the request is being overidden server-side. Any idea how to solve this?
I have dealt with the same and it can be solved via middleware.
Ah, nice one. Thanks @petrbrzek that looks like a good solution. I’ll have to try that out next time.
Sorry, I didn’t get notifications of these comments.