mirror of
https://github.com/umami-software/umami.git
synced 2026-02-04 12:47:13 +01:00
refactor(route): streamline Open Graph meta tag generation for bots
- Introduced a new metaTag function to simplify the creation of meta tags for Open Graph and Twitter. - Replaced regex-based bot detection with the isbot library for improved accuracy. - Enhanced the GET route to conditionally render meta tags based on available link metadata, improving SEO and social media sharing capabilities.
This commit is contained in:
parent
39d4c6fc93
commit
dd2de94548
1 changed files with 30 additions and 36 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
export const dynamic = 'force-dynamic';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
|
import { isbot } from 'isbot';
|
||||||
import { NextResponse } from 'next/server';
|
import { NextResponse } from 'next/server';
|
||||||
import { POST } from '@/app/api/send/route';
|
import { POST } from '@/app/api/send/route';
|
||||||
import type { Link } from '@/generated/prisma/client';
|
import type { Link } from '@/generated/prisma/client';
|
||||||
|
|
@ -16,6 +17,14 @@ function escapeHtml(str: string): string {
|
||||||
.replace(/'/g, ''');
|
.replace(/'/g, ''');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function metaTag(property: string, content: string | undefined, isName = false): string {
|
||||||
|
if (!content) return '';
|
||||||
|
const escaped = escapeHtml(content);
|
||||||
|
return isName
|
||||||
|
? `<meta name="${property}" content="${escaped}">`
|
||||||
|
: `<meta property="${property}" content="${escaped}">`;
|
||||||
|
}
|
||||||
|
|
||||||
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
|
export async function GET(request: Request, { params }: { params: Promise<{ slug: string }> }) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
|
|
||||||
|
|
@ -50,27 +59,12 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
|
||||||
}
|
}
|
||||||
|
|
||||||
const userAgent = request.headers.get('user-agent') || '';
|
const userAgent = request.headers.get('user-agent') || '';
|
||||||
const isBot =
|
|
||||||
/facebookexternalhit|twitterbot|linkedinbot|whatsapp|slackbot|discordbot|telegrambot|applebot|bingbot|googlebot/i.test(
|
|
||||||
userAgent,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isBot) {
|
if (isbot(userAgent)) {
|
||||||
const ogTitle = escapeHtml(link.ogTitle || link.name);
|
const ogTitle = link.ogTitle || link.name;
|
||||||
const ogDescription = escapeHtml(link.ogDescription || '');
|
const ogDescription = link.ogDescription || undefined;
|
||||||
const ogImageUrl = escapeHtml(link.ogImageUrl || '');
|
const ogImageUrl = link.ogImageUrl || undefined;
|
||||||
const ogDescriptionTag = ogDescription
|
|
||||||
? `<meta property="og:description" content="${ogDescription}">`
|
|
||||||
: '';
|
|
||||||
const ogImageTag = ogImageUrl ? `<meta property="og:image" content="${ogImageUrl}">` : '';
|
|
||||||
const twitterCard = ogImageUrl ? 'summary_large_image' : 'summary';
|
const twitterCard = ogImageUrl ? 'summary_large_image' : 'summary';
|
||||||
const metaDescriptionTag = ogDescription
|
|
||||||
? `<meta name="description" content="${ogDescription}">`
|
|
||||||
: '';
|
|
||||||
const twitterDescriptionTag = ogDescription
|
|
||||||
? `<meta name="twitter:description" content="${ogDescription}">`
|
|
||||||
: '';
|
|
||||||
const twitterImageTag = ogImageUrl ? `<meta name="twitter:image" content="${ogImageUrl}">` : '';
|
|
||||||
|
|
||||||
return new Response(
|
return new Response(
|
||||||
`
|
`
|
||||||
|
|
@ -78,29 +72,29 @@ export async function GET(request: Request, { params }: { params: Promise<{ slug
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>${ogTitle}</title>
|
<title>${escapeHtml(ogTitle)}</title>
|
||||||
|
${metaTag('title', ogTitle, true)}
|
||||||
<meta name="title" content="${ogTitle}">
|
${metaTag('description', ogDescription, true)}
|
||||||
${metaDescriptionTag}
|
${metaTag('og:type', 'website')}
|
||||||
|
${metaTag('og:site_name', 'Umami')}
|
||||||
<meta property="og:type" content="website">
|
${metaTag('og:title', ogTitle)}
|
||||||
<meta property="og:site_name" content="Umami">
|
${metaTag('og:url', request.url)}
|
||||||
<meta property="og:title" content="${ogTitle}">
|
${metaTag('og:description', ogDescription)}
|
||||||
<meta property="og:url" content="${request.url}">
|
${metaTag('og:image', ogImageUrl)}
|
||||||
${ogDescriptionTag}
|
|
||||||
${ogImageTag}
|
|
||||||
|
|
||||||
<meta name="twitter:card" content="${twitterCard}">
|
<meta name="twitter:card" content="${twitterCard}">
|
||||||
<meta name="twitter:title" content="${ogTitle}">
|
${metaTag('twitter:title', ogTitle, true)}
|
||||||
${twitterDescriptionTag}
|
${metaTag('twitter:description', ogDescription, true)}
|
||||||
${twitterImageTag}
|
${metaTag('twitter:image', ogImageUrl, true)}
|
||||||
</head>
|
</head>
|
||||||
<body></body>
|
<body>
|
||||||
|
<p>Redirecting to ${escapeHtml(link.url)}...</p>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'content-type': 'text/html',
|
'content-type': 'text/html',
|
||||||
|
'cache-control': 's-maxage=300, stale-while-revalidate',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue