From 072667548e7559a4fdc9667793d7b9927339af81 Mon Sep 17 00:00:00 2001 From: Luke Bussey Date: Thu, 6 Jul 2023 06:48:09 -0700 Subject: [PATCH 1/9] Update example to use segmentio/analytics-next and NextJS app layout --- examples/with-segment-analytics/README.md | 4 +-- .../{pages/about.js => app/about/page.tsx} | 4 +++ .../app/contact/page.tsx | 14 ++++++++ .../with-segment-analytics/app/layout.tsx | 21 +++++++++++ .../{pages/index.js => app/page.tsx} | 4 +++ .../with-segment-analytics/components/Page.js | 17 --------- .../components/analytics.tsx | 23 ++++++++++++ .../{pages/contact.js => components/form.tsx} | 14 ++++---- .../components/{Header.js => header.tsx} | 1 - examples/with-segment-analytics/package.json | 7 +++- examples/with-segment-analytics/pages/_app.js | 36 ------------------- examples/with-segment-analytics/tsconfig.json | 28 +++++++++++++++ 12 files changed, 109 insertions(+), 64 deletions(-) rename examples/with-segment-analytics/{pages/about.js => app/about/page.tsx} (70%) create mode 100644 examples/with-segment-analytics/app/contact/page.tsx create mode 100644 examples/with-segment-analytics/app/layout.tsx rename examples/with-segment-analytics/{pages/index.js => app/page.tsx} (70%) delete mode 100644 examples/with-segment-analytics/components/Page.js create mode 100644 examples/with-segment-analytics/components/analytics.tsx rename examples/with-segment-analytics/{pages/contact.js => components/form.tsx} (78%) rename examples/with-segment-analytics/components/{Header.js => header.tsx} (93%) delete mode 100644 examples/with-segment-analytics/pages/_app.js create mode 100644 examples/with-segment-analytics/tsconfig.json diff --git a/examples/with-segment-analytics/README.md b/examples/with-segment-analytics/README.md index 10906c1ac4f3c..53698224c130b 100644 --- a/examples/with-segment-analytics/README.md +++ b/examples/with-segment-analytics/README.md @@ -1,6 +1,6 @@ -# Example app with analytics +# With Segment Analytics -This example shows how to use Next.js along with [Segment Analytics](https://segment.com). A [custom app](https://nextjs.org/docs/advanced-features/custom-app) is used to inject the [Segment Analytics.js snippet](https://github.com/segmentio/snippet). The server and client-side call the [Page API](https://segment.com/docs/connections/spec/page/), while components call the [Track API](https://segment.com/docs/connections/spec/track/) on user actions (Refer to [`contact.js`](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics/pages/contact.js)). +This example shows how to use Next.js along with [Segment Analytics](https://segment.com) using [segmentio/analytics-next](https://github.com/segmentio/analytics-next). The main app [layout](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics/app/layout.tsx) includes a client component (analytics.tsx)[(https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics/components/analytics.tsx)] loads Segment and also exports the `analytics` object which can be imported and used to call the [Track API](https://segment.com/docs/connections/spec/track/) on user actions (Refer to [`contact.js`](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics/app/contact/page.tsx)). ## Deploy your own diff --git a/examples/with-segment-analytics/pages/about.js b/examples/with-segment-analytics/app/about/page.tsx similarity index 70% rename from examples/with-segment-analytics/pages/about.js rename to examples/with-segment-analytics/app/about/page.tsx index b7a8cc625091c..616ac9625aac4 100644 --- a/examples/with-segment-analytics/pages/about.js +++ b/examples/with-segment-analytics/app/about/page.tsx @@ -1,3 +1,7 @@ +export const metadata = { + title: 'About', +} + export default function About() { return (
diff --git a/examples/with-segment-analytics/app/contact/page.tsx b/examples/with-segment-analytics/app/contact/page.tsx new file mode 100644 index 0000000000000..e1223920f2453 --- /dev/null +++ b/examples/with-segment-analytics/app/contact/page.tsx @@ -0,0 +1,14 @@ +import Form from '@/components/form' + +export const metadata = { + title: 'Contact', +} + +export default function Contact() { + return ( +
+

This is the Contact page

+
+
+ ) +} diff --git a/examples/with-segment-analytics/app/layout.tsx b/examples/with-segment-analytics/app/layout.tsx new file mode 100644 index 0000000000000..d61385ceb3265 --- /dev/null +++ b/examples/with-segment-analytics/app/layout.tsx @@ -0,0 +1,21 @@ +import { Inter } from 'next/font/google' +import Header from '@/components/header' +import Analytics from '@/components/analytics' + +const inter = Inter({ subsets: ['latin'] }) + +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + + +
+ {children} + + + + ) +} diff --git a/examples/with-segment-analytics/pages/index.js b/examples/with-segment-analytics/app/page.tsx similarity index 70% rename from examples/with-segment-analytics/pages/index.js rename to examples/with-segment-analytics/app/page.tsx index f069f23390606..8c632f41fd25b 100644 --- a/examples/with-segment-analytics/pages/index.js +++ b/examples/with-segment-analytics/app/page.tsx @@ -1,3 +1,7 @@ +export const metadata = { + title: 'Home', +} + export default function Home() { return (
diff --git a/examples/with-segment-analytics/components/Page.js b/examples/with-segment-analytics/components/Page.js deleted file mode 100644 index c5d50c3e14295..0000000000000 --- a/examples/with-segment-analytics/components/Page.js +++ /dev/null @@ -1,17 +0,0 @@ -import React from 'react' -import Router from 'next/router' -import Header from './Header' - -// Track client-side page views with Segment -Router.events.on('routeChangeComplete', (url) => { - window.analytics.page(url) -}) - -const Page = ({ children }) => ( -
-
- {children} -
-) - -export default Page diff --git a/examples/with-segment-analytics/components/analytics.tsx b/examples/with-segment-analytics/components/analytics.tsx new file mode 100644 index 0000000000000..2528c09389465 --- /dev/null +++ b/examples/with-segment-analytics/components/analytics.tsx @@ -0,0 +1,23 @@ +'use client' + +import { useEffect } from 'react' +import { usePathname, useSearchParams } from 'next/navigation' +import { AnalyticsBrowser } from '@segment/analytics-next' + +// This write key is associated with https://segment.com/nextjs-example/sources/nextjs. +const DEFAULT_WRITE_KEY = 'NPsk1GimHq09s7egCUlv7D0tqtUAU5wa' + +export const analytics = AnalyticsBrowser.load({ + writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY || DEFAULT_WRITE_KEY, +}) + +export default function Analytics() { + const pathname = usePathname() + const searchParams = useSearchParams() + + useEffect(() => { + analytics.page() + }, [pathname, searchParams]) + + return null +} diff --git a/examples/with-segment-analytics/pages/contact.js b/examples/with-segment-analytics/components/form.tsx similarity index 78% rename from examples/with-segment-analytics/pages/contact.js rename to examples/with-segment-analytics/components/form.tsx index 1fd3f6936f230..5bc133c321caf 100644 --- a/examples/with-segment-analytics/pages/contact.js +++ b/examples/with-segment-analytics/components/form.tsx @@ -1,19 +1,20 @@ +'use client' import { useState } from 'react' +import { analytics } from '@/components/analytics' -const Contact = () => { +export default function Form() { const [message, setMessage] = useState('') - const handleSubmit = (e) => { + const handleSubmit = (e: React.FormEvent) => { e.preventDefault() - global.analytics.track('Form Submitted', { + analytics.track('Form Submitted', { message, }) setMessage('') } return ( -
-

This is the Contact page

+ <>
+ ) } -export default Contact diff --git a/examples/with-segment-analytics/components/Header.js b/examples/with-segment-analytics/components/header.tsx similarity index 93% rename from examples/with-segment-analytics/components/Header.js rename to examples/with-segment-analytics/components/header.tsx index 110f5c172f800..68edfe251205b 100644 --- a/examples/with-segment-analytics/components/Header.js +++ b/examples/with-segment-analytics/components/header.tsx @@ -1,4 +1,3 @@ -import React from 'react' import Link from 'next/link' export default function Header() { diff --git a/examples/with-segment-analytics/package.json b/examples/with-segment-analytics/package.json index e7f5b01511684..cf615a727fc7a 100644 --- a/examples/with-segment-analytics/package.json +++ b/examples/with-segment-analytics/package.json @@ -6,9 +6,14 @@ "start": "next start" }, "dependencies": { - "@segment/snippet": "^4.0.1", + "@segment/analytics-next": "1.53.0", "next": "latest", "react": "^18.2.0", "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/node": "20.4.0", + "@types/react": "18.2.14", + "typescript": "5.1.6" } } diff --git a/examples/with-segment-analytics/pages/_app.js b/examples/with-segment-analytics/pages/_app.js deleted file mode 100644 index 5c2c2bf7d0a2d..0000000000000 --- a/examples/with-segment-analytics/pages/_app.js +++ /dev/null @@ -1,36 +0,0 @@ -import Page from '../components/Page' -import Script from 'next/script' -import * as snippet from '@segment/snippet' - -// This write key is associated with https://segment.com/nextjs-example/sources/nextjs. -const DEFAULT_WRITE_KEY = 'NPsk1GimHq09s7egCUlv7D0tqtUAU5wa' - -function renderSnippet() { - const opts = { - apiKey: process.env.NEXT_PUBLIC_ANALYTICS_WRITE_KEY || DEFAULT_WRITE_KEY, - // note: the page option only covers SSR tracking. - // Page.js is used to track other events using `window.analytics.page()` - page: true, - } - - if (process.env.NODE_ENV === 'development') { - return snippet.max(opts) - } - - return snippet.min(opts) -} - -function MyApp({ Component, pageProps }) { - return ( - - {/* Inject the Segment snippet into the of the document */} -