Skip to content

Commit b525453

Browse files
authored
fix(next): track function ignored on hard refresh (#198)
1 parent 0d69416 commit b525453

16 files changed

Lines changed: 435 additions & 249 deletions

File tree

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Link from 'next/link';
2+
import styles from '../layout.module.css';
23

34
export default async function BlogPage({
45
params,
@@ -7,10 +8,15 @@ export default async function BlogPage({
78
}) {
89
const { slug } = await params;
910
return (
10-
<div>
11-
<h2>{slug}</h2>
12-
13-
<Link href="/blog">Back to blog</Link>
14-
</div>
11+
<>
12+
<span className={styles.badge}>Blog</span>
13+
<h1>{slug.replace(/-/g, ' ')}</h1>
14+
<p className={styles.description}>
15+
This is the post content for &ldquo;{slug}&rdquo;.
16+
</p>
17+
<Link className={styles.back} href="/blog">
18+
All posts
19+
</Link>
20+
</>
1521
);
1622
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
.page {
2+
display: flex;
3+
align-items: center;
4+
justify-content: center;
5+
min-height: 100svh;
6+
padding: 80px;
7+
font-family: var(--font-geist-sans);
8+
}
9+
10+
.main {
11+
display: flex;
12+
flex-direction: column;
13+
gap: 32px;
14+
max-width: 480px;
15+
width: 100%;
16+
}
17+
18+
.back {
19+
display: inline-flex;
20+
align-items: center;
21+
gap: 6px;
22+
font-size: 13px;
23+
color: rgba(0, 0, 0, 0.4);
24+
text-decoration: none;
25+
transition: color 0.15s;
26+
}
27+
28+
.back::before {
29+
content: "←";
30+
}
31+
32+
.badge {
33+
display: inline-flex;
34+
align-items: center;
35+
gap: 6px;
36+
font-size: 12px;
37+
font-weight: 500;
38+
letter-spacing: 0.04em;
39+
text-transform: uppercase;
40+
color: rgba(0, 0, 0, 0.4);
41+
}
42+
43+
.badge::before {
44+
content: "";
45+
display: block;
46+
width: 6px;
47+
height: 6px;
48+
border-radius: 50%;
49+
background: #3b82f6;
50+
}
51+
52+
.main h1 {
53+
font-size: 36px;
54+
font-weight: 600;
55+
letter-spacing: -0.03em;
56+
line-height: 1.15;
57+
margin: 0;
58+
}
59+
60+
.posts {
61+
display: flex;
62+
flex-direction: column;
63+
gap: 12px;
64+
}
65+
66+
.post {
67+
display: flex;
68+
align-items: center;
69+
justify-content: space-between;
70+
padding: 16px 20px;
71+
border-radius: 12px;
72+
border: 1px solid rgba(0, 0, 0, 0.08);
73+
font-size: 15px;
74+
font-weight: 500;
75+
transition:
76+
background 0.15s,
77+
border-color 0.15s;
78+
}
79+
80+
.post::after {
81+
content: "→";
82+
opacity: 0.4;
83+
}
84+
85+
.description {
86+
font-size: 15px;
87+
line-height: 1.6;
88+
color: rgba(0, 0, 0, 0.5);
89+
margin: 0;
90+
}
91+
92+
@media (hover: hover) and (pointer: fine) {
93+
.back:hover {
94+
color: var(--foreground);
95+
}
96+
97+
.post:hover {
98+
background: rgba(0, 0, 0, 0.04);
99+
border-color: rgba(0, 0, 0, 0.15);
100+
}
101+
102+
.post:hover::after {
103+
opacity: 1;
104+
}
105+
}
106+
107+
@media (prefers-color-scheme: dark) {
108+
.back {
109+
color: rgba(255, 255, 255, 0.4);
110+
}
111+
112+
.badge {
113+
color: rgba(255, 255, 255, 0.4);
114+
}
115+
116+
.post {
117+
border-color: rgba(255, 255, 255, 0.1);
118+
}
119+
120+
.post:hover {
121+
background: rgba(255, 255, 255, 0.05);
122+
border-color: rgba(255, 255, 255, 0.2);
123+
}
124+
125+
.description {
126+
color: rgba(255, 255, 255, 0.5);
127+
}
128+
}
129+
130+
@media (max-width: 600px) {
131+
.page {
132+
padding: 32px;
133+
align-items: flex-start;
134+
padding-top: 64px;
135+
}
136+
}
Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import Link from 'next/link';
2+
import styles from './layout.module.css';
23

34
export default function Layout({ children }: { children: React.ReactNode }) {
45
return (
5-
<div>
6-
<Link href="/blog/my-first-blogpost">My first blog post</Link>&nbsp;
7-
<Link href="/blog/new-feature-release">Feature just got released</Link>
8-
<br />
9-
<div>{children}</div>
6+
<div className={styles.page}>
7+
<main className={styles.main}>
8+
<Link className={styles.back} href="/">
9+
Home
10+
</Link>
11+
{children}
12+
</main>
1013
</div>
1114
);
1215
}
Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
import Link from 'next/link';
2+
import styles from './layout.module.css';
3+
14
export default function Blog() {
2-
return <div>Welcome to the blog</div>;
5+
return (
6+
<>
7+
<span className={styles.badge}>Blog</span>
8+
<h1>Posts</h1>
9+
<nav className={styles.posts}>
10+
<Link className={styles.post} href="/blog/my-first-blogpost">
11+
My first blog post
12+
</Link>
13+
<Link className={styles.post} href="/blog/new-feature-release">
14+
Feature just got released
15+
</Link>
16+
</nav>
17+
</>
18+
);
319
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'use client';
2+
import { track } from '@vercel/analytics/next';
3+
import { useEffect } from 'react';
4+
import styles from './page.module.css';
5+
6+
let tracked = false;
7+
8+
export function ExposureTracker() {
9+
useEffect(() => {
10+
if (tracked) return;
11+
tracked = true;
12+
track('exposure');
13+
}, []);
14+
15+
return (
16+
<button
17+
type="button"
18+
className={styles.button}
19+
onClick={() => track('click_cta')}
20+
>
21+
Try it out
22+
</button>
23+
);
24+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
.page {
2+
display: flex;
3+
align-items: center;
4+
justify-content: center;
5+
min-height: 100svh;
6+
padding: 80px;
7+
font-family: var(--font-geist-sans);
8+
}
9+
10+
.main {
11+
display: flex;
12+
flex-direction: column;
13+
gap: 32px;
14+
max-width: 480px;
15+
width: 100%;
16+
}
17+
18+
.badge {
19+
display: inline-flex;
20+
align-items: center;
21+
gap: 6px;
22+
font-size: 12px;
23+
font-weight: 500;
24+
letter-spacing: 0.04em;
25+
text-transform: uppercase;
26+
color: rgba(0, 0, 0, 0.4);
27+
}
28+
29+
.badge::before {
30+
content: "";
31+
display: block;
32+
width: 6px;
33+
height: 6px;
34+
border-radius: 50%;
35+
background: #22c55e;
36+
}
37+
38+
.main h1 {
39+
font-size: 36px;
40+
font-weight: 600;
41+
letter-spacing: -0.03em;
42+
line-height: 1.15;
43+
margin: 0;
44+
}
45+
46+
.description {
47+
font-size: 15px;
48+
line-height: 1.6;
49+
color: rgba(0, 0, 0, 0.5);
50+
margin: 0;
51+
}
52+
53+
.button {
54+
align-self: flex-start;
55+
appearance: none;
56+
background: var(--foreground);
57+
color: var(--background);
58+
border: none;
59+
border-radius: 10px;
60+
padding: 12px 20px;
61+
font-size: 14px;
62+
font-weight: 500;
63+
cursor: pointer;
64+
transition: opacity 0.15s;
65+
}
66+
67+
@media (hover: hover) and (pointer: fine) {
68+
.button:hover {
69+
opacity: 0.8;
70+
}
71+
}
72+
73+
.back {
74+
display: inline-flex;
75+
align-items: center;
76+
gap: 6px;
77+
font-size: 13px;
78+
color: rgba(0, 0, 0, 0.4);
79+
text-decoration: none;
80+
transition: color 0.15s;
81+
}
82+
83+
.back::before {
84+
content: "←";
85+
}
86+
87+
@media (hover: hover) and (pointer: fine) {
88+
.back:hover {
89+
color: var(--foreground);
90+
}
91+
}
92+
93+
@media (prefers-color-scheme: dark) {
94+
.badge {
95+
color: rgba(255, 255, 255, 0.4);
96+
}
97+
98+
.description {
99+
color: rgba(255, 255, 255, 0.5);
100+
}
101+
102+
.back {
103+
color: rgba(255, 255, 255, 0.4);
104+
}
105+
}
106+
107+
@media (max-width: 600px) {
108+
.page {
109+
padding: 32px;
110+
align-items: flex-start;
111+
padding-top: 64px;
112+
}
113+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import Link from 'next/link';
2+
import { ExposureTracker } from './exposure-tracker';
3+
import styles from './page.module.css';
4+
5+
export default function ExperimentPage() {
6+
return (
7+
<div className={styles.page}>
8+
<main className={styles.main}>
9+
<Link className={styles.back} href="/">
10+
Home
11+
</Link>
12+
<span className={styles.badge}>Experiment</span>
13+
<h1>See what we&apos;re testing</h1>
14+
<p className={styles.description}>
15+
This page is part of an active experiment. Your visit has been
16+
recorded as an exposure, and you can interact below to track
17+
additional events.
18+
</p>
19+
<ExposureTracker />
20+
</main>
21+
</div>
22+
);
23+
}

0 commit comments

Comments
 (0)