next-authnext.js14segment-io

Implementing Segment Analytics on Next.js 14 with NextAuth


I am attempting to implement Segment Analytics on my Next.js site. I am leveraging NextAuth for authentication through Google. All of this is working well, but I am now trying to call Segment's Identify method when the user logs in.

However, it does not appear that NextAuth emits a client-side event which I can listen for. I have found that I can attach to events on the server-side, but that doesn't help me.

/src/app/api/[...nextauth]/route.js:

import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";

export const authOptions = {
    providers: [
        GoogleProvider({
            clientId: process.env.GOOGLE_CLIENT_ID,
            clientSecret: process.env.GOOGLE_CLIENT_SECRET,
        }),
    ],
    events: {
        signIn: async (data) => {
            console.log("server-side signIn event detected", data);
        },
    },
};
export const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };

Any clever ideas on how I can push this down to the client, or leverage the client-side useSession hook to detect this? I would prefer to not call identify on every page load, and only call when the user actually just logged in.

I tried building a client-side function and import it to the server, but got the following error:

Attempted to call the default export of /SegmentIdentify.js from the server but it's on the client. It's not possible to invoke a client function from the server, it can only be rendered as a Component or passed to props of a Client Component.


Solution

  • If you're using signin() then based on the NextAuth docs about the signIn method, you could set redirect to false then save the output to a variable. Since signIn will then return a Promise, that resolves to the following:

    {
      /**
       * Will be different error codes,
       * depending on the type of error.
       */
      error: string | undefined
      /**
       * HTTP status code,
       * hints the kind of error that happened.
       */
      status: number
      /**
       * `true` if the signin was successful
       */
      ok: boolean
      /**
       * `null` if there was an error,
       * otherwise the url the user
       * should have been redirected to.
       */
      url: string | null
    }
    

    You can check if ok is true, then call the Segment Identify method. After that, you can manually redirect the user to another page if needed.