Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Example) Update with-segment-analytics to use segmentio/analytics-next and app layout #52327

Merged
merged 11 commits into from
Aug 30, 2023
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This write key is associated with https://segment.com/nextjs-example/sources/nextjs.
NEXT_PUBLIC_SEGMENT_WRITE_KEY=NPsk1GimHq09s7egCUlv7D0tqtUAU5wa
35 changes: 35 additions & 0 deletions examples/with-segment-analytics-pages-router/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
27 changes: 27 additions & 0 deletions examples/with-segment-analytics-pages-router/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# With Segment Analytics (Pages Router)

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 custom app [component](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics-pages-router/pages/_app_.tsx) includes a component (analytics.tsx)[(https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics-pages-router/components/analytics.tsx)] which 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.tsx`](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics-pages-router/pages/contact.tsx)).

## Deploy your own

Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example) or preview live with [StackBlitz](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-segment-analytics-pages-router)

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-segment-analytics-pages-router&project-name=with-segment-analytics-pages-router&repository-name=with-segment-analytics-pages-router)

## How to use

Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init), [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/), or [pnpm](https://pnpm.io) to bootstrap the example:

```bash
npx create-next-app --example with-segment-analytics-pages-router with-segment-analytics-app
```

```bash
yarn create next-app --example with-segment-analytics-pages-router with-segment-analytics-app
```

```bash
pnpm create next-app --example with-segment-analytics-pages-router with-segment-analytics-app
```

Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import { analytics } from '@/lib/segment'

export default function Analytics() {
const router = useRouter()

useEffect(() => {
analytics.page()

router.events.on('routeChangeComplete', () => analytics.page())

return () => {
router.events.off('routeChangeComplete', () => analytics.page())
}
}, [router.events])

return null
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { useState } from 'react'
import { analytics } from '@/lib/segment'

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 (
<div>
<h1>This is the Contact page</h1>
<>
<form onSubmit={handleSubmit}>
<label>
<span>Message:</span>
Expand Down Expand Up @@ -41,7 +41,6 @@ const Contact = () => {
display: block;
}
`}</style>
</div>
</>
)
}
export default Contact
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React from 'react'
import Link from 'next/link'

export default function Header() {
Expand Down
5 changes: 5 additions & 0 deletions examples/with-segment-analytics-pages-router/lib/segment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AnalyticsBrowser } from '@segment/analytics-next'

export const analytics = AnalyticsBrowser.load({
writeKey: process.env.NEXT_PUBLIC_SEGMENT_WRITE_KEY!,
})
19 changes: 19 additions & 0 deletions examples/with-segment-analytics-pages-router/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"private": true,
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@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"
}
}
16 changes: 16 additions & 0 deletions examples/with-segment-analytics-pages-router/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { AppProps } from 'next/app'
import { Inter } from 'next/font/google'
import Header from '@/components/header'
import Analytics from '@/components/analytics'

const inter = Inter({ subsets: ['latin'] })

export default function MyApp({ Component, pageProps }: AppProps) {
return (
<main className={inter.className}>
<Header />
<Component {...pageProps} />
<Analytics />
</main>
)
}
14 changes: 14 additions & 0 deletions examples/with-segment-analytics-pages-router/pages/about.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Head from 'next/head'

export default function About() {
return (
<>
<Head>
<title>About</title>
</Head>
<div>
<h1>This is the About page</h1>
</div>
</>
)
}
16 changes: 16 additions & 0 deletions examples/with-segment-analytics-pages-router/pages/contact.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Head from 'next/head'
import Form from '@/components/form'

export default function Contact() {
return (
<>
<Head>
<title>Contact</title>
</Head>
<div>
<h1>This is the Contact page</h1>
<Form />
</div>
</>
)
}
14 changes: 14 additions & 0 deletions examples/with-segment-analytics-pages-router/pages/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Head from 'next/head'

export default function Home() {
return (
<>
<Head>
<title>Home</title>
</Head>
<div>
<h1>This is the Home page</h1>
</div>
</>
)
}
28 changes: 28 additions & 0 deletions examples/with-segment-analytics-pages-router/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
2 changes: 2 additions & 0 deletions examples/with-segment-analytics/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This write key is associated with https://segment.com/nextjs-example/sources/nextjs.
NEXT_PUBLIC_SEGMENT_WRITE_KEY=NPsk1GimHq09s7egCUlv7D0tqtUAU5wa
4 changes: 2 additions & 2 deletions examples/with-segment-analytics/README.md
Original file line number Diff line number Diff line change
@@ -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)] which 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.tsx`](https://github.com/vercel/next.js/blob/canary/examples/with-segment-analytics/app/contact/page.tsx)).

## Deploy your own

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export const metadata = {
title: 'About',
}

export default function About() {
return (
<div>
Expand Down
14 changes: 14 additions & 0 deletions examples/with-segment-analytics/app/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Form from '@/components/form'

export const metadata = {
title: 'Contact',
}

export default function Contact() {
return (
<div>
<h1>This is the Contact page</h1>
<Form />
</div>
)
}
21 changes: 21 additions & 0 deletions examples/with-segment-analytics/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<html>
<body className={inter.className}>
<Header />
{children}
</body>
<Analytics />
</html>
)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export const metadata = {
title: 'Home',
}

export default function Home() {
return (
<div>
Expand Down
17 changes: 0 additions & 17 deletions examples/with-segment-analytics/components/Page.js

This file was deleted.

16 changes: 16 additions & 0 deletions examples/with-segment-analytics/components/analytics.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
'use client'

import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
import { analytics } from '@/lib/segment'

export default function Analytics() {
lukebussey marked this conversation as resolved.
Show resolved Hide resolved
const pathname = usePathname()
const searchParams = useSearchParams()

useEffect(() => {
analytics.page()
}, [pathname, searchParams])

return null
}
48 changes: 48 additions & 0 deletions examples/with-segment-analytics/components/form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
'use client'

import { useState } from 'react'
import { analytics } from '@/lib/segment'

export default function Form() {
const [message, setMessage] = useState('')

const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
analytics.track('Form Submitted', {
message,
})
setMessage('')
}

return (
<>
<form onSubmit={handleSubmit}>
<label>
<span>Message:</span>
<textarea
onChange={(e) => setMessage(e.target.value)}
value={message}
/>
</label>
<button type="submit">submit</button>
</form>

<style jsx>{`
label span {
display: block;
margin-bottom: 12px;
}

textarea {
min-width: 300px;
min-height: 120px;
}

button {
margin-top: 12px;
display: block;
}
`}</style>
</>
)
}
Loading