Postulate is the best way to take and share notes for classes, research, and other learning.
Segment is a powerful analytics tool that allows you to track user behavior on your app and pipeline that data to various destinations. It boasts a simple installation process, which is well-documented on its Getting Started page. For React, and Next.js in particular, though, we'll have to make a few small changes to get things up and running.
For these changes, I referenced Vercel's official with-segment-analytics
example, with a few more of my own tweaks. Here's how I ultimately ended up setting up Segment in Postulate:
If you don't have a pages/_document.tsx
file yet, create one. In its <Head>
tag, plop in the following code to load Segment into your clientside app:
<Head>
<script dangerouslySetInnerHTML={{__html: `
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t,e){var n=document.createElement("script");n.type="text/javascript";n.async=!0;n.src="https://cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(n,a);analytics._loadOptions=e};analytics.SNIPPET_VERSION="4.1.0";
analytics.load("${process.env.SEGMENT_WRITE_KEY}");
analytics.page();
}}();
`}}>
</script>
</Head>
Inside analytics.load
, place your own Segment write key. I'm using an environment variable since I have different write keys for development and production environments.
In a plain website, the above script would execute every time a new page is loaded, logging the appropriate page view in Segment. In a React app, however, the page route can change without the page being reloaded, so we need to make a manual analytics.page
call on route change.
In Next.js, this can be accomplished by adding an event handler outside of the main component in _app.tsx
:
Router.events.on("routeChangeComplete", (url) => {
// @ts-ignore window.analytics undefined below
window.analytics.page(url);
});
export default function App({Component, pageProps}: AppProps) {
...
}
The script we added earlier binds analytics
to window
, but Typescript doesn't know about this, so we add a @ts-ignore
to supress any errors.
Segment allows users to be identified with a analytics.identify
call. In Postulate, I set up a useEffect
hook in the navbar so that as soon as my authenticated user session loads in, I make an identify call to let Segment know who is being tracked.
useEffect(() => {
// @ts-ignore window.analytics undefined below
if (session) window.analytics.identify(session.userId, {
username: session.username,
email: session.user.email,
});
}, [loading]);
session
and loading
are specific here to NextAuth, the Auth solution I use for Postulate. Your implementation may look a little different.
Lastly, Segment can also be used to track specific user actions or events. In this case, I set up a simple item creation event, calling analytics.track
when a project, snippet, or post is created:
// @ts-ignore
window.analytics.track("Item created", {
type: "project",
projectId: res.data.id,
});
With all this set up, I can now happily watch data stream into the Segment debugger:
Founder and dev notes from building Postulate