From b915f15ed964424d97e996add04e24465c65d748 Mon Sep 17 00:00:00 2001 From: crbon Date: Thu, 8 Jan 2026 14:43:41 +1000 Subject: [PATCH] feat(analytics): add custom metadata support for shared links - Add custom title field for user-defined link names - Implement custom OG image URL input for social media previews - Enable Open Graph metadata customization (description, type, etc.) - Add link slug/path customization for personalized URLs - Update link creation form with new metadata fields - Extend database schema to store custom link properties - Add validation for OG image URLs and metadata inputs This allows users to fully customize their shared analytics links with custom titles, Open Graph images, and other metadata for better social media presentation and link management. --- prisma/schema.prisma | 3 +++ src/app/(collect)/q/[slug]/route.ts | 33 +++++++++++++++++++++++++++ src/app/(main)/links/LinkEditForm.tsx | 30 ++++++++++++------------ src/app/api/links/[linkId]/route.ts | 7 ++++-- src/app/api/links/route.ts | 8 ++++++- 5 files changed, 64 insertions(+), 17 deletions(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index aeb11648..aa11b854 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -281,6 +281,9 @@ model Link { name String @db.VarChar(100) url String @db.VarChar(500) slug String @unique() @db.VarChar(100) + title String? @db.VarChar(500) + description String? @db.VarChar(500) + image String? @db.VarChar(500) userId String? @map("user_id") @db.Uuid teamId String? @map("team_id") @db.Uuid createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) diff --git a/src/app/(collect)/q/[slug]/route.ts b/src/app/(collect)/q/[slug]/route.ts index 24089bdb..eb0587f1 100644 --- a/src/app/(collect)/q/[slug]/route.ts +++ b/src/app/(collect)/q/[slug]/route.ts @@ -40,6 +40,39 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug } } + const userAgent = request.headers.get('user-agent') || ''; + const isBot = + /facebookexternalhit|twitterbot|linkedinbot|whatsapp|slackbot|discordbot|telegrambot|applebot|bingbot|googlebot/i.test( + userAgent, + ); + const l = link; + if (isBot && (l.title || l.description || l.image)) { + return new Response( + ` + + + + + + + + + + + + + + + + `, + { + headers: { + 'content-type': 'text/html', + }, + }, + ); + } + const payload = { type: 'event', payload: { diff --git a/src/app/(main)/links/LinkEditForm.tsx b/src/app/(main)/links/LinkEditForm.tsx index 6c10c7f0..bd1ffa8d 100644 --- a/src/app/(main)/links/LinkEditForm.tsx +++ b/src/app/(main)/links/LinkEditForm.tsx @@ -101,26 +101,28 @@ export function LinkEditForm({ - - + + + + + + + + + + - + > + +