Add PostHog analytics — full event tracking across all pages

Tracks pageviews, hero/CTA clicks, product teaser clicks, app card
and detail views, newsletter signups, nav interactions, and footer
link clicks with structured properties for PostHog dashboards.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tim Leikauf
2026-07-01 20:59:29 +02:00
parent 7f67d123d6
commit 0101447d84
14 changed files with 248 additions and 64 deletions

View File

@@ -1,10 +1,8 @@
import type { Metadata } from 'next'
import Link from 'next/link'
'use client'
export const metadata: Metadata = {
title: 'Fittimo Bewegung im Alltag | HyggeCraftery',
description: 'Sanfte Bewegung und Atemübungen für Körper und Geist im Einklang.',
}
import Link from 'next/link'
import { useEffect } from 'react'
import { posthog } from '@/lib/posthog'
const accent = '#7DAF8A'
@@ -16,6 +14,10 @@ const features = [
]
export default function FittimoPage() {
useEffect(() => {
posthog.capture('app_detail_viewed', { app: 'fittimo' })
}, [])
return (
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
@@ -98,7 +100,11 @@ export default function FittimoPage() {
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
Fittimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
</p>
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
<Link
href="/#newsletter"
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'fittimo' })}
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
>
Benachrichtigen lassen
</Link>
</div>

View File

@@ -1,10 +1,7 @@
import type { Metadata } from 'next'
import Link from 'next/link'
'use client'
export const metadata: Metadata = {
title: 'Apps HyggeCraftery',
description: 'Drei sanfte Apps für einen langsameren, bewussteren Alltag.',
}
import Link from 'next/link'
import { posthog } from '@/lib/posthog'
const apps = [
{
@@ -56,6 +53,7 @@ export default function AppsPage() {
<Link
key={app.name}
href={app.href}
onClick={() => posthog.capture('app_card_clicked', { app_name: app.name })}
style={{
textDecoration: 'none',
display: 'grid',

View File

@@ -1,10 +1,8 @@
import type { Metadata } from 'next'
import Link from 'next/link'
'use client'
export const metadata: Metadata = {
title: 'Rezeptimo Kochen mit Freude | HyggeCraftery',
description: 'Saisonale Rezepte zum langsamen Kochen — ehrlich, einfach, nährend.',
}
import Link from 'next/link'
import { useEffect } from 'react'
import { posthog } from '@/lib/posthog'
const accent = '#C4896A'
@@ -16,6 +14,10 @@ const features = [
]
export default function RezeptimoPage() {
useEffect(() => {
posthog.capture('app_detail_viewed', { app: 'rezeptimo' })
}, [])
return (
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
@@ -98,7 +100,11 @@ export default function RezeptimoPage() {
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
Rezeptimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
</p>
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
<Link
href="/#newsletter"
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'rezeptimo' })}
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
>
Benachrichtigen lassen
</Link>
</div>

View File

@@ -1,10 +1,8 @@
import type { Metadata } from 'next'
import Link from 'next/link'
'use client'
export const metadata: Metadata = {
title: 'Snakkimo Sprachen lernen | HyggeCraftery',
description: 'Sprachen lernen, das sich anfühlt wie durch einen schönen Feed scrollen. Kleine Lektionen, großer Effekt.',
}
import Link from 'next/link'
import { useEffect } from 'react'
import { posthog } from '@/lib/posthog'
const accent = '#7BA7BC'
@@ -16,6 +14,10 @@ const features = [
]
export default function SnakkimoPage() {
useEffect(() => {
posthog.capture('app_detail_viewed', { app: 'snakkimo' })
}, [])
return (
<div style={{ fontFamily: 'var(--font-mulish, Mulish, sans-serif)', color: '#3D2B1F', background: '#FAFAF7', overflow: 'hidden' }}>
@@ -98,7 +100,11 @@ export default function SnakkimoPage() {
<p style={{ fontSize: 16, color: 'rgba(250,250,247,0.65)', margin: '0 0 40px', lineHeight: 1.7 }}>
Snakkimo erscheint bald. Trage dich in unseren Newsletter ein und erfahre als Erste davon.
</p>
<Link href="/#newsletter" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}>
<Link
href="/#newsletter"
onClick={() => posthog.capture('newsletter_cta_clicked', { source: 'app_page', app_name: 'snakkimo' })}
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 10, background: accent, color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, padding: '16px 36px', borderRadius: 44 }}
>
Benachrichtigen lassen
</Link>
</div>

9
app/layout.tsx Normal file → Executable file
View File

@@ -3,6 +3,7 @@ import { Cormorant_Garamond, Mulish } from 'next/font/google'
import './globals.css'
import Nav from '@/components/ui/Nav'
import Footer from '@/components/ui/Footer'
import PostHogProvider from '@/components/PostHogProvider'
const cormorant = Cormorant_Garamond({
subsets: ['latin'],
@@ -45,9 +46,11 @@ export default function RootLayout({
backgroundImage: `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E")`,
}}
/>
<Nav />
<main>{children}</main>
<Footer />
<PostHogProvider>
<Nav />
<main>{children}</main>
<Footer />
</PostHogProvider>
</body>
</html>
)

View File

@@ -1,6 +1,9 @@
'use client'
import Image from 'next/image'
import Link from 'next/link'
import NewsletterForm from '@/components/ui/NewsletterForm'
import { posthog } from '@/lib/posthog'
export default function HomePage() {
return (
@@ -21,11 +24,19 @@ export default function HomePage() {
Handgemachte Stücke und sanfte Rituale für ein Zuhause, das zur Ruhe einlädt. Wir feiern das Langsame, das Echte, das Wesentliche.
</p>
<div style={{ display: 'flex', alignItems: 'center', gap: 22 }}>
<Link href="/shop" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, background: '#C4896A', color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, letterSpacing: 0.3, padding: '16px 32px', borderRadius: 44 }}>
<Link
href="/shop"
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/shop', label: 'Entdecken' })}
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, background: '#C4896A', color: '#FAFAF7', fontSize: 15.5, fontWeight: 600, letterSpacing: 0.3, padding: '16px 32px', borderRadius: 44 }}
>
Entdecken
<span style={{ display: 'inline-block', width: 18, height: 18, borderRadius: '50%', border: '1.5px solid rgba(250,250,247,0.6)' }} />
</Link>
<Link href="/#ueber" style={{ textDecoration: 'none', fontSize: 15, fontWeight: 600, color: '#3D2B1F', borderBottom: '1.5px solid #A8B89A', paddingBottom: 3 }}>
<Link
href="/#ueber"
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/#ueber', label: 'Unsere Geschichte' })}
style={{ textDecoration: 'none', fontSize: 15, fontWeight: 600, color: '#3D2B1F', borderBottom: '1.5px solid #A8B89A', paddingBottom: 3 }}
>
Unsere Geschichte
</Link>
</div>
@@ -68,14 +79,23 @@ export default function HomePage() {
Stücke fürs Zuhause
</h2>
</div>
<Link href="/shop" style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, border: '1.5px solid #3D2B1F', color: '#3D2B1F', fontSize: 15, fontWeight: 600, padding: '14px 28px', borderRadius: 44 }}>
<Link
href="/shop"
onClick={() => posthog.capture('hero_cta_clicked', { destination: '/shop', label: 'Zum Shop' })}
style={{ textDecoration: 'none', display: 'inline-flex', alignItems: 'center', gap: 11, border: '1.5px solid #3D2B1F', color: '#3D2B1F', fontSize: 15, fontWeight: 600, padding: '14px 28px', borderRadius: 44 }}
>
Zum Shop <span style={{ fontSize: 18, lineHeight: 1 }}></span>
</Link>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 30 }}>
{shopProducts.map((p) => (
<Link key={p.name} href="/shop" style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}>
<Link
key={p.name}
href="/shop"
onClick={() => posthog.capture('product_teaser_clicked', { product_name: p.name, price: p.price })}
style={{ textDecoration: 'none', color: 'inherit', display: 'block' }}
>
<div style={{ position: 'relative', height: 360, borderRadius: 30, overflow: 'hidden', background: p.bg, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', padding: 18 }}>
{p.badge && (
<span style={{ position: 'absolute', top: 18, left: 18, background: '#A8B89A', color: '#FAFAF7', fontSize: 11.5, fontWeight: 700, letterSpacing: 0.6, padding: '6px 13px', borderRadius: 30 }}>
@@ -117,7 +137,11 @@ export default function HomePage() {
</div>
<h3 style={{ fontFamily: 'var(--font-cormorant, "Cormorant Garamond", serif)', fontWeight: 600, fontSize: 27, margin: '0 0 10px', color: '#FAFAF7' }}>{app.name}</h3>
<p style={{ fontSize: 14.5, color: 'rgba(250,250,247,0.6)', margin: '0 0 22px' }}>{app.desc}</p>
<Link href={app.href} style={{ textDecoration: 'none', fontSize: 14.5, fontWeight: 600, color: app.linkColor, borderBottom: `1.5px solid ${app.linkColor}50`, paddingBottom: 2 }}>
<Link
href={app.href}
onClick={() => posthog.capture('app_teaser_clicked', { app_name: app.name })}
style={{ textDecoration: 'none', fontSize: 14.5, fontWeight: 600, color: app.linkColor, borderBottom: `1.5px solid ${app.linkColor}50`, paddingBottom: 2 }}
>
Mehr erfahren
</Link>
</div>
@@ -139,7 +163,7 @@ export default function HomePage() {
<p style={{ fontSize: 16, color: '#8a7a68', margin: '0 auto 36px', maxWidth: 460 }}>
Sanfte Geschichten, saisonale Rituale und stille Inspiration etwa einmal im Monat, ganz ohne Eile.
</p>
<NewsletterForm />
<NewsletterForm source="homepage" />
</div>
</div>
</section>

View File

@@ -1,10 +1,7 @@
import type { Metadata } from 'next'
import Link from 'next/link'
'use client'
export const metadata: Metadata = {
title: 'Shop HyggeCraftery',
description: 'Handgemachte Stücke für ein langsameres, schöneres Zuhause.',
}
import Link from 'next/link'
import { posthog } from '@/lib/posthog'
const products = [
{ name: 'Leinen-Kissen «Fjord»', price: '€ 48', desc: 'Sanftes Leinen in gedämpftem Salbei.', badge: 'Neu', bg: 'repeating-linear-gradient(40deg,#F0E8DA,#F0E8DA 11px,#E7DDCC 11px,#E7DDCC 22px)' },
@@ -46,7 +43,11 @@ export default function ShopPage() {
{/* Product grid */}
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gap: 30 }}>
{products.map((p) => (
<div key={p.name} style={{ display: 'block', color: 'inherit' }}>
<div
key={p.name}
onClick={() => posthog.capture('product_viewed', { product_name: p.name, price: p.price })}
style={{ display: 'block', color: 'inherit', cursor: 'pointer' }}
>
<div style={{ position: 'relative', height: 360, borderRadius: 30, overflow: 'hidden', background: p.bg, display: 'flex', alignItems: 'flex-end', justifyContent: 'center', padding: 18 }}>
{p.badge && (
<span style={{ position: 'absolute', top: 18, left: 18, background: p.badge === 'Bald' ? '#C4896A' : '#A8B89A', color: '#FAFAF7', fontSize: 11.5, fontWeight: 700, letterSpacing: 0.6, padding: '6px 13px', borderRadius: 30 }}>