Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: facebook metadata #65713

Merged
merged 7 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions docs/02-app/02-api-reference/04-functions/generate-metadata.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,51 @@ export const metadata = {
<meta name="category" content="technology" />
```

### `facebook`

You can connect a Facebook app or Facebook account to you webpage for certain Facebook Social Plugins [Facebook Documentation](https://developers.facebook.com/docs/plugins/comments/#moderation-setup-instructions)

> **Good to know**: You can specify either appId or admins, but not both.

```jsx filename="layout.js | page.js"
export const metadata = {
facebook: {
appId: '12345678',
},
}
```

```html filename="<head> output" hideLineNumbers
<meta property="fb:app_id" content="12345678" />
```

```jsx filename="layout.js | page.js"
export const metadata = {
facebook: {
admins: '12345678',
},
}
```

```html filename="<head> output" hideLineNumbers
<meta property="fb:admins" content="12345678" />
```

If you want to generate multiple fb:admins meta tags you can use array value.

```jsx filename="layout.js | page.js"
export const metadata = {
facebook: {
admins: ['12345678', '87654321'],
},
}
```

```html filename="<head> output" hideLineNumbers
<meta property="fb:admins" content="12345678" />
<meta property="fb:admins" content="87654321" />
```

### `other`

All metadata options should be covered using the built-in support. However, there may be custom metadata tags specific to your site, or brand new metadata tags just released. You can use the `other` option to render any custom metadata tag.
Expand Down
1 change: 1 addition & 0 deletions packages/next/src/lib/metadata/default-metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export function createDefaultMetadata(): ResolvedMetadata {
appleWebApp: null,
formatDetection: null,
itunes: null,
facebook: null,
abstract: null,
appLinks: null,
archives: null,
Expand Down
17 changes: 17 additions & 0 deletions packages/next/src/lib/metadata/generate/basic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ export function ItunesMeta({ itunes }: { itunes: ResolvedMetadata['itunes'] }) {
return <meta name="apple-itunes-app" content={content} />
}

export function FacebookMeta({
facebook,
}: {
facebook: ResolvedMetadata['facebook']
}) {
if (!facebook) return null

const { appId, admins } = facebook

return MetaFilter([
appId ? <meta property="fb:app_id" content={appId} /> : null,
...(admins
? admins.map((admin) => <meta property="fb:admins" content={admin} />)
: []),
])
}

const formatDetectionKeys = [
'telephone',
'date',
Expand Down
2 changes: 2 additions & 0 deletions packages/next/src/lib/metadata/metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
BasicMeta,
ViewportMeta,
VerificationMeta,
FacebookMeta,
} from './generate/basic'
import { AlternatesMetadata } from './generate/alternate'
import {
Expand Down Expand Up @@ -131,6 +132,7 @@ export function createMetadataComponents({
BasicMeta({ metadata }),
AlternatesMetadata({ alternates: metadata.alternates }),
ItunesMeta({ itunes: metadata.itunes }),
FacebookMeta({ facebook: metadata.facebook }),
FormatDetectionMeta({ formatDetection: metadata.formatDetection }),
VerificationMeta({ verification: metadata.verification }),
AppleWebAppMeta({ appleWebApp: metadata.appleWebApp }),
Expand Down
5 changes: 5 additions & 0 deletions packages/next/src/lib/metadata/resolve-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import {
resolveThemeColor,
resolveVerification,
resolveItunes,
resolveFacebook,
} from './resolvers/resolve-basics'
import { resolveIcons } from './resolvers/resolve-icons'
import { getTracer } from '../../server/lib/trace/tracer'
Expand Down Expand Up @@ -198,6 +199,10 @@ function mergeMetadata({
)
break
}
case 'facebook':
target.facebook = resolveFacebook(source.facebook)
break

case 'verification':
target.verification = resolveVerification(source.verification)
break
Expand Down
8 changes: 8 additions & 0 deletions packages/next/src/lib/metadata/resolvers/resolve-basics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,11 @@ export const resolveItunes: FieldResolverExtraArgs<
: undefined,
}
}

export const resolveFacebook: FieldResolver<'facebook'> = (facebook) => {
if (!facebook) return null
return {
appId: facebook.appId,
admins: resolveAsArrayOrUndefined(facebook.admins),
}
}
14 changes: 14 additions & 0 deletions packages/next/src/lib/metadata/types/extra-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,20 @@ export type ResolvedAppleWebApp = {
statusBarStyle?: 'default' | 'black' | 'black-translucent'
}

export type Facebook = FacebookAppId | FacebookAdmins
export type FacebookAppId = {
appId: string
admins?: never
}
export type FacebookAdmins = {
appId?: never
admins: string | string[]
}
export type ResolvedFacebook = {
appId?: string
admins?: string[]
}

// Format Detection
// This is a poorly specified metadata export type that is supposed to
// control whether the device attempts to conver text that matches
Expand Down
23 changes: 23 additions & 0 deletions packages/next/src/lib/metadata/types/metadata-interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import type {
import type {
AppleWebApp,
AppLinks,
Facebook,
FormatDetection,
ItunesApp,
ResolvedAppleWebApp,
ResolvedAppLinks,
ResolvedFacebook,
ViewportLayout,
} from './extra-types'
import type {
Expand Down Expand Up @@ -320,6 +322,25 @@ interface Metadata extends DeprecatedMetadataFields {
*/
twitter?: null | Twitter

/**
* The Facebook metadata for the document.
* You can specify either appId or admins, but not both.
* @example
* ```tsx
* { appId: "12345678" }
*
* <meta property="fb:app_id" content="12345678" />
* ```
*
* @example
* ```tsx
* { admins: ["12345678"] }
*
* <meta property="fb:admins" content="12345678" />
* ```
*/
facebook?: null | Facebook

/**
* The common verification tokens for the document.
* @example
Expand Down Expand Up @@ -508,6 +529,8 @@ interface ResolvedMetadata extends DeprecatedMetadataFields {

twitter: null | ResolvedTwitterMetadata

facebook: null | ResolvedFacebook

// common verification tokens
verification: null | ResolvedVerification

Expand Down
13 changes: 13 additions & 0 deletions test/e2e/app-dir/metadata/app/facebook/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export default function page() {
return 'facebook'
}

export async function generateMetadata() {
const metadata = {
facebook: {
appId: '12345678',
admins: ['120', '122', '124'],
},
}
return metadata
}
10 changes: 10 additions & 0 deletions test/e2e/app-dir/metadata/metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ describe('app dir - metadata', () => {
)
})

it('should support facebook related tags', async () => {
const browser = await next.browser('/facebook')
const matchMultiDom = createMultiDomMatcher(browser)

await matchMultiDom('meta', 'property', 'content', {
'fb:app_id': '12345678',
'fb:admins': ['120', '122', '124'],
})
})

it('should support alternate tags', async () => {
const browser = await next.browser('/alternates')
const matchDom = createDomMatcher(browser)
Expand Down
Loading