Pixel is an open source analytics library for NextJS applications. It is designed to be embedded in your NextJS application, so that you can get the most accurate events data. All events are sent to your own domain -- not a third-party address -- allowing you to neatly integrate with authentication, avoid using cookies, keep user data safe, and bypass browser blockers too.
Start by installing the package.
yarn add @pixel/nextjs
Generate a special secret that is used to sign JWTs
npx uuid
Add this special UUID to your environment variables:
PIXEL_JWT_SECRET="<your UUID>"
Start by creating a new pixel.ts
file at the root of your app with the following content. This example uses a BigQuery adapter, but you can choose any (see below)
import Pixel from '@pixel/nextjs';
import { Pixel, BigQueryAdapter } from '@/pixel/server';
import { BigQuery } from '@google-cloud/bigquery';
import { auth } from '@/auth';
const client = new BigQuery(...);
export default new Pixel({
adapter: new BigQueryAdapter(client),
auth,
})
Currently Pixel supports sending events to:
But it is also extremely easy to build your own adapter. Simply take a look at the existing ones and it should be pretty clear.
This means that any events that are tracked on the client are sent to your own domain, not a third party domain which can be blocked.
These instructions are for nextjs applications using App Router
Create an API route in app/api/events/route.ts
with the following code:
import { handlers } from '@pixel/nextjs';
import pixel from '@/pixel';
export const { POST } = handlers(pixel);
If you want to put this route in a custom location, see these instructions
This should go into your layout.tsx
if you use the app router, or your _app.tsx
file if you use the pages router. The following example uses the NextJS app router, but the same logic applies.
import { PixelProvider } from '@pixel/nextjs';
export default function Layout({ children }: { children: ReactNode }) {
return (
<PixelProvider>
<html lang="en">
<body>{children}</body>
</html>
</PixelProvider>
);
}
When you "identify" a user, you are providing additional information about them to Pixel, such as their email, name, image, and any other arbitrary stuff you want to include.
Pixel does not immediately store or process any of this data. It will simply mint a JWT with the information, which the client will then save to local storage in the browser.
Any events triggered from the client side will automatically include this JWT, and will be sent to the backend along with each event.
Here is how you can identify a user on the frontend. Note that the only mandatory field is email
.
import { usePixel } from '@pixel/nextjs';
export function AuthComponent() {
const { identify } = usePixel();
const handleClick = () => {
identify({
email: '[email protected]',
name: 'Bill Gates', // optional
image: 'https://microsoft.com/bill.png', // optional
userId: 1, // optional
data: {
// optionally include any fields in here
company: 'Microsoft',
companyId: 'MS',
},
});
};
return (
<div>
<button onClick={handleClick}>Log in</button>
</div>
);
}
On the client side of your app, you can easily use the React hook. Here's an example:
import { usePixel } from '@pixel/nextjs';
export function MyComponent() {
const { track } = usePixel();
const handleClick = () => {
track('Awesome event');
};
return (
<div>
<button onClick={handleClick}>Click me</button>
</div>
);
}
On the server side of your app, you can track using the Pixel client we set up earlier. Let's take a look:
import pixel from '@/pixel';
pixel.track('Cool event');