Implementation Patterns

Structured Data & Custom Code

Brease provides two components for injecting page-level metadata into your rendered output: BreaseStructuredData for JSON-LD structured data and BreaseCustomCode for arbitrary scripts and HTML. This page covers both components plus site-level custom code.


BreaseStructuredData

Renders JSON-LD <script> tags from the structured data configured on a page in the CMS.

Usage

import { BreaseStructuredData } from 'brease-next'

export default async function Page({ params }) {
  const { slug } = await params
  const slugStr = (slug ?? []).join('/')
  const page = ensureSuccess(await getPage(slugStr))

  return (
    <>
      <BreaseStructuredData page={page} />
      <BreasePage page={page} sectionMap={componentMap} />
    </>
  )
}

How it works

  • Reads page.structuredData, which is an array of structured data objects defined in the CMS
  • Renders each object as a <script type="application/ld+json"> tag
  • Returns null if page.structuredData is null, undefined, or an empty array

Example output

If the CMS has a page with an Organization schema configured, the component renders:

<script type="application/ld+json">
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "name": "Acme Corp",
    "url": "https://acme.com"
  }
</script>

Setting up structured data in the CMS

  1. Open a page in the Brease editor
  2. Navigate to the page's SEO settings
  3. Add structured data entries using the JSON-LD editor
  4. Choose from common schemas (Organization, Article, Product, FAQ, etc.) or write custom JSON-LD

Validate your structured data

Use Google's Rich Results Test to verify your JSON-LD output. Errors in structured data will not break rendering but will prevent rich results in search engines.


BreaseCustomCode

Renders page-level custom code defined in the CMS. This is typically used for analytics snippets, tracking pixels, chat widgets, or inline HTML/CSS that applies to a specific page.

Usage

import { BreaseCustomCode } from 'brease-next'

export default async function Page({ params }) {
  const { slug } = await params
  const slugStr = (slug ?? []).join('/')
  const page = ensureSuccess(await getPage(slugStr))

  return (
    <>
      <BreaseStructuredData page={page} />
      <BreasePage page={page} sectionMap={componentMap} />
      <BreaseCustomCode page={page} />
    </>
  )
}

How it works

  • Reads page.customCode, which contains raw HTML/script content defined in the CMS
  • Renders the content using dangerouslySetInnerHTML
  • Returns null if page.customCode is null, undefined, or empty

Common use cases

  • Page-specific analytics events
  • Embedded widgets (calendars, booking forms)
  • Conversion tracking pixels
  • Custom CSS overrides for a single page

Full Page Component Example

Here is a complete page component with both structured data and custom code:

// src/app/[[...slug]]/page.tsx
import { notFound } from 'next/navigation'
import {
  BreasePage,
  BreaseStructuredData,
  BreaseCustomCode,
  generateBreasePageParams,
  generateBreasePageMetadata,
  ensureSuccess,
} from 'brease-next'
import { componentMap } from '@/lib/brease/config'
import { getPage } from '@/lib/brease/get-page'

export async function generateStaticParams() {
  return generateBreasePageParams()
}

export async function generateMetadata({
  params,
}: {
  params: Promise<{ slug?: string[] }>
}) {
  const { slug } = await params
  const slugStr = (slug ?? []).join('/')
  const result = await getPage(slugStr)

  if (!result.success) return {}

  return generateBreasePageMetadata(result.data, {
    metadataBase: 'https://example.com',
  })
}

export default async function Page({
  params,
}: {
  params: Promise<{ slug?: string[] }>
}) {
  const { slug } = await params
  const slugStr = (slug ?? []).join('/')
  const result = await getPage(slugStr)

  if (!result.success) {
    notFound()
  }

  const page = ensureSuccess(result)

  return (
    <>
      <BreaseStructuredData page={page} />
      <BreasePage page={page} sectionMap={componentMap} />
      <BreaseCustomCode page={page} />
    </>
  )
}

Component Placement Summary

ComponentData sourceWhere to place
BreaseStructuredDatapage.structuredDataBefore or after BreasePage in the page component
BreaseCustomCodepage.customCodeAfter BreasePage in the page component

Both BreaseStructuredData and BreaseCustomCode are safe to include unconditionally. They render nothing when their data is empty.


Next Steps

Previous
Media & Images