✨ Watch on YouTube | 🐙 GitHub | 🎮 Demo
Let’s add Amplitude analytics to a NextJS app!
Get Radzion’s stories in your inbox
Join Medium for free to get updates from this writer.
In the example below, we will track page views by calling the trackEvent method on the analytics instance from the useEffect hook:
function MyApp({ Component, pageProps }: AppProps) {
const { pathname } = router
useEffect(() => {
analytics.trackEvent("Visit page", { pathname })
}, [pathname])
return <p>my app</p>
}
export default MyAppThis is how you create the analytics instance for your app:
import { isProduction } from "shared"
import { shouldBeDefined } from "@increaser/utils/shouldBeDefined"
import { AmplitudeAnalytics } from "@increaser/ui/analytics/AmplitudeAnalytics"
import { LocalAnalytics } from "@increaser/ui/analytics/LocalAnalytics"
export const analytics = isProduction
? new AmplitudeAnalytics(
shouldBeDefined(process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY)
)
: new LocalAnalytics()First, we check if the environment is set to production. We want to avoid sending analytics events in development or testing environments.
export const isProduction = process.env.NODE_ENV === "production"The shouldBeDefined function will throw an error if the value is undefined. This is useful to ensure we never forget to set the environment variable.
export function shouldBeDefined<T>(
value: T | undefined,
valueName: string = "value"
): T {
if (value === undefined) {
throw new Error(`${valueName} is undefined`)
}
return value
}Both AmplitudeAnalytics and LocalAnalytics adhere to the same interface, which should include:
setUser: used to associate the user with the analytics events. This would only be used if your app or website has authenticated users.trackEvent: used to track events. Extra info can be passed into the second argument, such as the name of the page in our previous example.
export interface Analytics {
setUser: (id: string) => void
trackEvent: (name: string, data?: Record<string, any>) => void
}Here’s how you would implement AmplitudeAnalytics:
import { Analytics } from "./Analytics"
import * as amplitude from "@amplitude/analytics-browser"
export class AmplitudeAnalytics implements Analytics {
apiKey: string
isInitialized: boolean = false
constructor(apiKey: string) {
this.apiKey = apiKey
}
private initialize() {
if (!this.isInitialized) {
amplitude.init(this.apiKey)
this.isInitialized = true
}
}
setUser(id: string) {
this.initialize()
amplitude.setUserId(id)
}
trackEvent(name: string, data?: Record<string, any>) {
this.initialize()
amplitude.track(name, data)
}
}It requires the @amplitude/analytics-browser package to be installed and an apiKey to be passed as a constructor argument. We don't initialize Amplitude immediately; instead, we only do so the first time setUser or trackEvent is called. This ensures that requests are only sent to Amplitude upon tracking.
Here’s how you can implement LocalAnalytics:
import { Analytics } from "./Analytics"
export class LocalAnalytics implements Analytics {
constructor() {
console.log("Initialize local analytics")
}
setUser(id: string) {
console.log("Set user for analytics: ", id)
}
trackEvent(name: string, data?: Record<string, any>) {
console.log("Track event: ", name, data)
}
}This merely logs the events to the console. It’s useful for debugging events during development.







