Private profile pages that emit OpenGraph tags leak user identity to search crawlers and social preview scrapers, violating GDPR Art. 25 (data protection by design). A user who marks their profile private reasonably expects that og:title, og:image, and og:description do not appear in Google's index or in link previews shared by third parties. Simultaneously, public profiles without OpenGraph metadata miss every social share amplification opportunity — both failure modes live in the same generateMetadata function.
Medium because the leak is passive — crawlers must visit the page — but the privacy violation is real and the SEO cost of missing metadata is measurable.
In app/users/[id]/page.tsx, return robots: 'noindex' from generateMetadata whenever the profile is private or the viewer is unauthorized. For public profiles, populate the full OpenGraph object.
// app/users/[id]/page.tsx
export async function generateMetadata({ params }: { params: { id: string } }) {
const user = await getUserProfile(params.id)
if (!user || user.is_private) {
return { robots: { index: false, follow: false } }
}
return {
title: `${user.name} — YourApp`,
description: user.bio ?? `See ${user.name}'s profile on YourApp`,
openGraph: {
title: user.name,
description: user.bio ?? '',
images: user.avatar ? [{ url: user.avatar, width: 400, height: 400 }] : [],
type: 'profile'
}
}
}
ID: community-social-engagement.profiles-identity.profile-seo-metadata
Severity: medium
What to look for: Enumerate all relevant files and Check the dynamic profile route for metadata generation. Look for generateMetadata functions (Next.js App Router) or getStaticProps/getServerSideProps (Pages Router) that set OpenGraph tags based on the user's profile data. Verify that private profiles do not generate indexable metadata and have noindex headers or meta tags when viewing a private profile as an unauthorized user.
Pass criteria: At least 1 implementation must be present. Public profile pages generate OpenGraph metadata including og:title, og:description, and og:image based on the user's profile. Private profiles are either not indexable or return 404/401 to unauthenticated users.
Fail criteria: No metadata generation for profiles, or private profiles generate OpenGraph tags that leak information to crawlers.
Skip (N/A) when: Profiles are not public-facing or SEO is not a concern for this platform.
Detail on fail: "Profile pages have no generateMetadata function. OpenGraph tags are not set." or "Private profile pages generate og:title even when viewer is not authorized"
Remediation: Generate metadata for public profiles:
// app/users/[id]/page.tsx
export async function generateMetadata({ params }) {
const user = await getUserProfile(params.id)
if (!user || user.is_private) {
return { robots: 'noindex' }
}
return {
title: `${user.name} on YourApp`,
description: user.bio || `Profile of ${user.name}`,
openGraph: {
title: user.name,
description: user.bio,
images: [{ url: user.avatar, width: 200, height: 200 }],
type: 'profile'
}
}
}