Public Profile SEO & OpenGraph
Why it matters
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.
Severity rationale
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.
Remediation
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'
}
}
}
Detection
-
ID:
profile-seo-metadata -
Severity:
medium -
What to look for: Enumerate all relevant files and Check the dynamic profile route for metadata generation. Look for
generateMetadatafunctions (Next.js App Router) orgetStaticProps/getServerSideProps(Pages Router) that set OpenGraph tags based on the user's profile data. Verify that private profiles do not generate indexable metadata and havenoindexheaders 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, andog:imagebased 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' } } }
External references
- gdpr · Art. 25 — Data Protection by Design and by Default
Taxons
History
- 2026-04-18·v1.0.0·Initial import from community-social-engagement·automated