Setting up and using Mixpanel in Next.js
Introduction
So I built this web application called YTPlay a couple of months ago, it's a YouTube Playlist downloader built with Next.js and shadcn, and in the past few months it hasn't been getting much traffic (maybe 100 visitors a month) and I have been using Vercel's Web Analytics tool but something happened within the last week or so and the site blew up (in comparison to previous usage) and now it had about 1000 visitors in the last 2 weeks and about 4000+ views, this led to Vercel pausing my analytics because they only allow a maximum of 2500 events per month on their free tier.
This means to continue seeing my traffic I'd have to pay Vercel $20/month or finally migrate to Mixpanel which I've been putting off for way too long so today I'll show you what Mixpanel is, why you should use it, how to set it up, what client and server-side tracking is and when to use each and some additional techniques along the way.
What is Mixpanel
Mixpanel is an advanced analytics platform designed to help businesses understand how users interact with their web and mobile applications. It provides detailed insights into user behavior, allowing companies to track and analyze user actions, measure engagement, and make data-driven decisions to improve their products and services.
Why Mixpanel
The main reasons I am using Mixpanel are I have used it before, it's really easy to set up and their free tier gives me access to 20 million monthly events, so if I only track page views I won't have to pay anything until my app has had more than 20 million monthly page views which I think is insane coming from what Vercel is offering.
Besides my main reasons for using Mixpanel here are some of its features that may interest you:
Event Tracking: Mixpanel allows you to track any event easily both on the client side and server side. You might be thinking what exactly is an event and why is this a big deal? An event is any action performed on your app, this can mean clicking a button, signing in, or adding an item to a cart. Mixpanel also allows you to send custom properties to each event being sent so for example you can send the add item to cart event with additional properties of the product being added to their cart and in Mixpanel you can see the product users add to their cart the most.
User Profiles: Mixpanel gives you a section on your dashboard called "Users" which allows you to save user information which can then be integrated with Mixpanel events by identifying user events, so you can click on a user and see what they have performed or click on an event and see what users are performing that event. Let's say you add a field for users called verify account or upgrade account, you can easily get data for all users who haven't verified or upgraded their account and directly reach out to them.
Integration: Mixpanel also easily integrates with a lot of other tools popular for making data-driven decisions. E.g you can take data from Mixpanel and use that to set your email marketing campaigns with Mailchimp, or set up ads with Google/Facebook and see how users who are coming from certain ad campaigns are more/less likely to perform certain actions which would let you know if an ad campaign is successful. Let's say you run two ad campaigns on Facebook talking about a certain service on your product, you can then use Mixpanel to find out if the users who are coming from Facebook are interacting with those services which can help you to refine your UI/UX, price or anything else you believe would make users click on your ad, go to your site for a service but not interact with that service.
Funneling: "A marketing funnel is the purchase cycle consumers go through from awareness to loyalty." - Amazon Advertising.
With Mixpanel you can easily create funnels and see the number of users who are making it from Ad campaign/Viewing a service -> Creating an account -> Interacting with your products -> Making a Purchase. This can help you to revise something in your strategy if you notice users dropping off heavily at one of these points it's a sign to reanalyze your strategy.
At this point, you might feel overwhelmed or think Mixpanel isn't a tool for you but if all you want to do is track how many users are visiting your site, you can set that up in 5 minutes and be done with, these additional tools are for teams trying to make data-driven decisions and are not mandatory to use.
How to use Mixpanel
There are two main ways you can use Mixpanel in the browser with any framework, using the mixpanel-browser
package or using the analytics
package with @analytics/mixpanel
.
First, you'll need to create an account on https://mixpanel.com, complete the onboarding process, create a new project, navigate to that project settings, get the project token, and then follow the remaining instructions using the tool of your choice.
mixpanel-browser
Using the mixpanel-browser
SDK you can instantiate a mix panel instance with your project token and use that to track events, so in this sample app, I have the code below in my /lib/mixpanel.ts
file.
PS: I have my setup like this because I have two Mixpanel projects I created so when running locally the data being sent doesn't affect my production traffic
import mixpanel from "mixpanel-browser";
const test = process.env.NEXT_PUBLIC_MIXPANEL_TEST_TOKEN;
const live = process.env.NEXT_PUBLIC_MIXPANEL_LIVE_TOKEN;
let token = "";
if (process.env.NODE_ENV === "development") {
token = test;
} else {
token = live;
}
mixpanel.init(token, {
track_pageview: true,
persistence: "localStorage",
});
export default mixpanel;
I set track_pageview
to true even though the default config does that because the docs said track_pageview
is set to false on SPAs (Single Page Applications).
Lookup the default config passed to the mixpanel.init
function here.
And now I can use it anywhere in my application
import mixpanel from "@/lib/mixpanel";
mixpanel.track("Event", { propertyOne, propertyTwo }) // sample
function addToCart() {
// add to cart logic
mixpanel.track("Add to Cart", { id: product?.id, name: product?.name })
}
PS: If you only want to track page views and nothing else this wouldn't work because although you're exporting the Mixpanel instance you aren't calling it anywhere so Mixpanel doesn't know to trac
analytics
It's a similar process with the analytics
package, You can create a file called /lib/analytics.ts
and paste the code below
import Analytics from 'analytics'
import mixpanelPlugin from '@analytics/mixpanel'
const test = process.env.NEXT_PUBLIC_MIXPANEL_TEST_TOKEN;
const live = process.env.NEXT_PUBLIC_MIXPANEL_LIVE_TOKEN;
let token = "";
if (process.env.NODE_ENV === "development") {
token = test as string;
} else {
token = live as string;
}
const analytics = Analytics({
app: 'my-app',
plugins: [
mixpanelPlugin({
token,
track_pageview: true,
persistence: "localStorage",
})
]
})
export default analytics
And then use it anywhere in your app
import analytics from "@/lib/analytics";
analytics.track("Event", { propertyOne, propertyTwo }) // sample
function addToCart() {
// add to cart logic
analytics.track("Add to Cart", { id: product?.id, name: product?.name })
}
Using Mixpanel in my app
The first thing I did was to run the below commands
npm i mixpanel mixpanel-browser
npm i -D @types/mixpanel-browser
to install the Mixpanel browser, nodejs SDKs, and type declarations. This is because my project uses Next.js API routes and I want to perform some tracking on the server side as well.
I then modified my lib to look like this so I could import from the same file
//src/lib/mixpanel.ts
import { InitConfig, Mixpanel as IMixpanelServer } from "mixpanel";
import { Config, Mixpanel as IMixpanelClient } from "mixpanel-browser";
const test = process.env.NEXT_PUBLIC_MIXPANEL_TEST_TOKEN;
const live = process.env.NEXT_PUBLIC_MIXPANEL_LIVE_TOKEN;
let token = "";
let options: Partial<Config | InitConfig> = {};
let mixpanel;
if (process.env.NODE_ENV === "development") {
token = test as string;
options = {
debug: true,
};
} else {
token = live as string;
}
if (typeof window === "undefined") {
mixpanel = require("mixpanel");
mixpanel.init(token as string, { ...options });
console.log("Using Server Side Mixpanel");
} else {
mixpanel = require("mixpanel-browser");
mixpanel.init(token as string, {
...options,
persistence: "localStorage",
});
console.log("Using Client Side Mixpanel");
}
export default mixpanel as IMixpanelClient & IMixpanelServer;
Usage:
// Server
import { mixpanelServer as mixpanel } from "@/lib/mixpanel";
// Client
import { mixpanelClient as mixpanel } from "@/lib/mixpanel";
Next, I decided what I wanted to track, these were;
Page Views
Number of times a playlist is requested
Number of times a user downloads a playlist/video
Number of users that clicked on the "How it Works"
Tracking Events
Mixpanel recommends using the server-side to track events when you can and then using the client whenever you can't this is because people a lot of people use adblockers or Brave Browser (myself included) which would cause tracking requests to be rejected and sometimes network requests just fail on the client so you'll have more accurate data if you send the event to Mixpanel once your server processes it, but in situations where there's no server interaction or you don't have access to the server (maybe you work strictly on the frontend or you're using a BAAS (Backend-as-a-Service) tool and have no control over the backend) you can setup Mixpanel client side but it's good to understand the drawbacks.
Brave rejects a tracking network request.
Taking note of everything I just mentioned when we want to implement tracking we are going to check if it's possible to do it on the backend and if not we'll do it on the frontend.
Page Views
Tracking a page view isn't possible on the backend due to the nature of my application (It's a Next.js app deployed to Vercel) I don't control the server sending the HTML content but what I can do is send the event on page load and send a new event every time the user changes route.
export default function Mixpanel() {
const router = useRouter();
useEffect(() => {
const handleRouteChange = (url: string) => {
console.log("Tracking pageview for", url);
mixpanel.track("Page View", { page: url });
};
router.events.on("routeChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}, [router.events]);
return null;
}
I can then use it in my _app.tsx
file
import Mixpanel from "@/components/Mixpanel"
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Component {...pageProps} />
<Mixpanel />
</>
)
}
No of times a playlist is requested
I can track when a playlist is requested by just sending an event to Mixpanel from my API route whenever a playlist request is made
mixpanel.track("Fetch Playlist");
return res.status(200).json(playlist);
I also have caching set up and I want to track the number of times data is gotten from my cache, this can help me know whether it's beneficial to my users or if it's just a waste of time.
if (cachedData) {
mixpanel.track("Fetch Playlist", { fromCache: true });
return res.status(200).json(cachedData);
}
No of times a user downloads a playlist
Once again I can send an event to Mixpanel when the server responds with the data stream so I'll do this server-side.
res.setHeader("Content-Length", totalSize);
mixpanel.track("Download Playlist", { id, quality, name: playlist?.title });
zip.generateNodeStream({ streamFiles: true }).pipe(res);
No of users that clicked on the "How it Works"
I implemented a walkthrough guide in my application, this activates by clicking on the "How it works" text in the navbar, I'd like to know if my users are actually using this feature so I'll check how many of them clicked on it by sending an event to mixpanel when the text is clicked.
function startTour() {
mixpanel.track("Started Walkthrough");
setIsOpen(true);
setIsNavOpen(false);
}
return (
// rest of the code
<span onClick={startTour} className="cursor-pointer">
How it Works
</span>
)
Conclusion
So in this article, we've learned what Mixpanel is, the benefits of using it, how to use it in a full-stack environment like Next.js, tradeoffs between Server-side and Client-side tracking, and examples of times we'd use one over the other.
If you noticed any errors in the article or need further clarification on anything you can reach out to me on X (twitter) or LinkedIn and I'll try my best to answer as soon as possible.
Subscribe to my newsletter
Read articles from Judge-Paul Ogebe directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Judge-Paul Ogebe
Judge-Paul Ogebe
software dev trying a bit of everything, linux fanboy