BUILDER.IO SEO AUDIT · VISUAL HEADLESS CMS · NEXT.JS · REACT
Free Builder.io SEO Audit
Builder.io is a visual headless CMS — it provides structured SEO fields (title, description, image) on Page models and serves content via its API, but all meta tag output, JSON-LD, sitemaps, and Core Web Vitals are determined by the Next.js (or Nuxt, SvelteKit, Astro) frontend consuming the Builder API. DeepSEOAnalysis audits the rendered frontend HTML — validating JSON-LD from Builder components, real CrUX Core Web Vitals, sitemap coverage from the Builder Content API, and all five AI visibility signals — with Builder model field paths and frontend component locations for every finding.
WHAT WE CHECK
6 Builder.io-specific SEO checks
Builder.io SEO auditing covers Page model SEO fields and generateMetadata() output, URL path routing and draft content exposure, JSON-LD in registered Builder components with property-level validation, Builder Content API-driven sitemap coverage, real CrUX Core Web Vitals with Builder CDN image and ISR configuration, and AI visibility — with Builder editor paths and frontend SDK integration locations for each finding.
Builder.io SEO fields and generateMetadata() output
Builder.io includes built-in SEO fields (title, description, image) on Page content models, accessible via `page.data` in the Next.js SDK. The audit validates the rendered meta tag output. The audit checks: meta title presence and quality (Builder\'s built-in `data.title` field feeds `generateMetadata()` — if editors leave it empty, the frontend must have a fallback, typically the page name; pages where the fallback is used rather than a custom SEO title are flagged); meta description coverage (Builder\'s built-in `data.description` field — empty field means no meta description unless the frontend auto-generates from body content; all pages with missing meta descriptions are flagged); canonical tag accuracy (Builder doesn\'t auto-generate canonical tags — the Next.js page component must explicitly set the canonical via `generateMetadata()` alternates.canonical, using either a custom canonical_url field from Builder data or the page\'s URL path; missing canonical tags on Builder pages are common when the metadata integration is incomplete); Open Graph tag completeness (Builder\'s built-in `data.image` provides the OG image — verify the OG image URL is absolute and returns a 200 response from Builder\'s CDN at cdn.builder.io; og:title and og:description must also be set in metadata); and noindex inconsistencies (if a custom noindex field is added to Builder pages, the frontend must read it in `generateMetadata()` and set `robots: "noindex"` — AND exclude the page from the sitemap; the audit checks for pages that are both in the sitemap and returning a noindex meta tag).
Builder.io URL routing and content model structure
Builder.io\'s URL path field (the "URL" field on Page content entries in the Builder editor) maps to frontend routes. The audit checks: URL path quality (the URL path on each Builder Page entry determines the public URL — auto-generated paths from page names can include spaces (converted to hyphens) or capitalisation inconsistencies; the audit checks for non-canonical URL patterns visible in the canonical tag); `generateStaticParams()` coverage (Next.js static generation for Builder.io pages requires fetching all published page URLs via the Builder Content API — `builder.getAll("page", { fields: "data.url", options: { limit: 1000 } })` — then generating static params from the URL paths; pages in the sitemap that return 404 indicate gaps in `generateStaticParams()` or Builder content that isn\'t published); draft content exposure (Builder.io draft pages should not be accessible on the public site — verify that the Builder SDK fetch uses `options: { cachebust: false }` only in preview mode, and that the public API call uses no preview headers for public users); redirect handling (Builder.io doesn\'t manage frontend redirects natively — a redirects content model in Builder or Next.js `next.config.js` static redirects array handles 301/302 for renamed or moved Builder pages); and multi-environment routing (Builder.io supports multiple environments — Development, Staging, Production — verify that the Space ID and public API key used in the production deploy point to the Production environment, not a staging environment).
JSON-LD structured data in Builder components
Builder.io\'s visual editor allows editors to compose pages from registered components. JSON-LD structured data must be implemented as registered custom components or as page-level metadata from Builder fields — the audit validates all JSON-LD found in the rendered HTML. The audit checks `Article` JSON-LD: `headline` should come from `content.data.title` (or a custom `seo_title` field), must be under 110 characters; `datePublished` from `content.data.createdDate` (millisecond Unix timestamp) must be formatted as ISO 8601 string; `dateModified` from `content.data.lastUpdated`; `author` as a `Person` object (requires a custom author field in the Builder Page model — a reference field to an Author content model, or a simple text field for author name); `image` as an absolute URL from Builder\'s CDN. For `FAQPage` JSON-LD: the audit checks that `mainEntity` has at least 2 `Question` objects, each with `name` (question text) and `acceptedAnswer.@type: "Answer"` with `text` (answer text). A common Builder-specific error is implementing the FAQ as a Builder Section component with visual question/answer styling but no corresponding JSON-LD output — editors create visual FAQ sections but the JSON-LD component isn\'t registered or dragged onto the page. The audit catches this as a visible FAQ section with no matching FAQPage JSON-LD. All JSON-LD must be in the server-rendered HTML — Builder custom components render server-side, but if JSON-LD is placed in a client-only component or uses `useEffect` for injection, it will appear only in the rendered DOM, not the raw HTML.
Builder Content API sitemap and indexing configuration
Builder.io has no native sitemap generation — the Next.js frontend must query the Builder Content API to generate `app/sitemap.ts`. The audit checks: sitemap accessibility (the Next.js `app/sitemap.ts` generates /sitemap.xml — verify it\'s accessible and returns valid XML); Builder content coverage (the sitemap should include all published Builder Page entries; query via `builder.getAll("page", { fields: "data.url,data.lastUpdated,data.noindex", options: { limit: 1000 } })` — filter out entries where `data.noindex: true` before adding to the sitemap); `lastmod` accuracy (Builder\'s `lastUpdated` field provides the last modification timestamp in milliseconds — convert via `new Date(entry.data.lastUpdated).toISOString()` for the sitemap `lastModified` property); custom content model inclusion (if using Builder.io for non-page content types — blog posts, product pages, landing pages in separate Builder models — each model\'s published entries must be separately queried and included in the sitemap); noindex exclusion (pages with `data.noindex: true` in Builder must be excluded from the sitemap; the audit flags pages that are both noindexed and in the sitemap as a configuration conflict); and robots.txt configuration (the `app/robots.ts` should declare `Sitemap:` pointing to the sitemap URL and disallow `/api/` and any Builder webhook endpoints).
Core Web Vitals for Builder.io-powered sites
Builder.io renders page content via its SDK — Core Web Vitals depend on how the Builder SDK renders blocks on the frontend and which framework stack is used. The audit uses real CrUX field data. **LCP** — the LCP element on most Builder pages is a hero image configured via a Builder Image block or a custom component. Builder.io images are served from cdn.builder.io with format transformation: `https://cdn.builder.io/api/v1/image/assets/[SPACE_ID]/[ASSET_ID]?format=webp&width=1200`. For Next.js: configure `cdn.builder.io` in `next.config.js` `images.remotePatterns`, then use Next.js `Image` with a custom Builder image component registered via `Builder.registerComponent()`. The custom image component should set the `priority` prop on hero images (the first image in the Builder page layout) to add `fetchpriority="high"` and disable lazy loading. **INP** — Builder.io\'s `RenderBuilderContent` component hydrates the full page client-side. Builder.io v2 (the `@builder.io/sdk-react` package) uses React Server Components where possible, reducing client-side JavaScript. Ensure you\'re using Builder SDK v2+ for optimal RSC support. **CLS** — Builder Image blocks must specify explicit dimensions — either fixed width/height or aspect ratio constraints. Builder\'s visual editor allows editors to set image dimensions; verify that the registered Image component reads and applies these dimensions as `width` and `height` attributes to prevent layout shifts. **TTFB** — Builder.io supports Next.js ISR via `revalidate` in `getBuilderStaticProps`. Set `revalidate: 60` (or appropriate interval) and use Builder\'s webhook to trigger on-demand revalidation when content is published.
AI visibility for Builder.io sites
Builder.io\'s visual editor environment makes AI visibility configuration a developer task — editors configure content in the visual canvas, but llms.txt, robots.ts, and FAQPage JSON-LD registration are code-level. For `llms.txt`: add `app/llms.txt/route.ts` to the Next.js project that generates an llms.txt file — optionally querying the Builder Content API for a curated list of key pages and their descriptions. The Builder `data.description` field provides per-page descriptions suitable for inclusion in llms.txt. For `robots.ts`: in `app/robots.ts`, ensure AI crawler user agents (GPTBot, ClaudeBot, PerplexityBot, AppleBot) are not in any Disallow block. The Builder.io CDN (cdn.builder.io) is not your origin — only your frontend domain\'s robots.txt matters for AI crawler access to your content. For `FAQPage` JSON-LD: register a custom Builder FAQ component that: (1) accepts a Builder editor array input of question/answer pairs; (2) renders the questions visually as a styled FAQ section; and (3) outputs FAQPage JSON-LD via `dangerouslySetInnerHTML` in the same server component. This way, when editors drag the FAQ component onto a page and fill in questions, the JSON-LD is automatically generated from the same data. For question-heading ratio: Builder blocks that editors drag onto pages may not automatically use H2/H3 elements — verify that Builder\'s registered Text/Heading components render the correct heading hierarchy, and that the Builder default heading block uses `<h2>` not `<div>` for section headings. The audit checks all five GEO signals in the rendered HTML with Builder-specific fix locations.
HOW IT WORKS
Audit your Builder.io site in 60 seconds
- Enter your frontend URL. Use the public URL of your Builder.io-powered frontend — not the Builder.io admin at builder.io/content, not the CDN at cdn.builder.io. No Builder.io API keys, Space ID, or admin credentials needed. Works with any frontend framework consuming Builder.io: Next.js (App Router or Pages Router), Nuxt, SvelteKit, Astro, Angular, or a custom React integration.
- We crawl and analyse. The engine validates all meta tags output by
generateMetadata()from Builder content fields; checks every JSON-LD block (Article, FAQPage, BreadcrumbList) against Google's Rich Results specifications with property-level errors; verifies the Builder Content API-driven sitemap covers all published pages (not drafts); measures CrUX Core Web Vitals from real Chrome field data; and evaluates all five AI visibility signals in the server-rendered HTML. - You get a prioritised report. Builder-specific issues first — empty SEO field fallbacks reverting to page names, missing FAQPage JSON-LD on pages with visible FAQ sections, Builder CDN OG images using relative URLs, draft content accessible at public routes, LCP Builder Image blocks without priority prop, missing llms.txt — then general SEO, each with the Builder editor path or frontend SDK file location for the fix.
FAQ
Questions about the Builder.io SEO audit
Does Builder.io have built-in SEO features?
Builder.io (builder.io) is a visual headless CMS and developer platform that includes structured SEO support through its content model and SDK. Builder.io\'s built-in SEO capabilities: (1) **SEO fields in Builder content models** — every Builder Page model (and custom models) includes a built-in "SEO" section with fields for title, description, and image in the Builder visual editor. These fields are accessible in `page.data` in the Next.js integration: `page.data.title`, `page.data.description`, `page.data.image`. (2) **URL handling** — Builder.io uses a URL path field on each Page content entry that maps to the frontend routing. The URL path is configurable per page in the Builder visual editor and consumed by `getBuilderStaticProps()` or the `useBuilderReactComponents()` hook for dynamic routes. (3) **Preview mode** — Builder.io has a draft/preview mode that serves unpublished content to authenticated previews without exposing draft content to public users or Googlebot (draft pages return 404 from the public API until published). (4) **Scheduled publishing** — Builder allows scheduling content publication, which means pages can be noindexed via the Builder SDK until the scheduled publish date, then auto-published. (5) **Custom fields** — the Builder.io content model supports custom fields of any type: text, rich text, boolean, file, reference. Adding a canonical_url text field, a noindex boolean field, og_image file field, and schema_type select field to the Page model provides full SEO field control per page without code changes.
How do I implement generateMetadata() with Builder.io in Next.js?
In a Next.js App Router application using Builder.io, `generateMetadata()` reads from Builder Page content fields fetched via the `@builder.io/sdk-react` or `@builder.io/sdk` package. Pattern: fetch the Builder page content by URL path using `builder.get("page", { userAttributes: { urlPath: "/" + params.slug } })`, then map the Builder content fields to Next.js metadata. The Builder Page model includes built-in SEO fields accessible via `content?.data`: `content.data.title` (meta title), `content.data.description` (meta description), `content.data.image` (OG image URL from Builder\'s CDN). For custom fields added to the Page model (canonical_url, noindex, og_title): access them at `content.data.canonical_url`, `content.data.noindex`, etc. The full `generateMetadata()` pattern: `const content = await builder.get("page", { fields: "data", userAttributes: { urlPath: "/" + params.slug.join("/") } }).toPromise(); const data = content?.data; return { title: data?.title, description: data?.description, alternates: { canonical: data?.canonical_url ?? \`/\${params.slug?.join("/")}\` }, openGraph: { images: data?.image ? [data.image] : [defaultOgImage] }, robots: data?.noindex ? "noindex" : "index, follow" }`. Key: use `fields: "data"` in the Builder query to reduce response payload — you don\'t need the full block tree for metadata.
How do I add JSON-LD structured data to Builder.io pages?
JSON-LD structured data in Builder.io-powered Next.js sites can be implemented through two patterns: (1) **Builder Custom Component with JSON-LD output** — create a custom React component registered with Builder.io\'s `Builder.registerComponent()` that outputs a `script type="application/ld+json"` tag. The component can accept inputs configured by editors in the Builder visual editor: for a FAQPage component, the inputs would be an array of `{question: string, answer: string}` items. The component renders the FAQPage JSON-LD from these inputs using `dangerouslySetInnerHTML`. Since Builder renders custom components server-side (React Server Components or `RenderBuilderContent` on the server), the JSON-LD is present in the initial HTML response. (2) **Page-level JSON-LD from Builder fields** — add a `json_ld_type` select field and `faq_items` JSON field to the Builder Page model. In the Next.js page component, read `content.data.json_ld_type` and `content.data.faq_items` alongside the page render and output the appropriate JSON-LD block in the page\'s `head` via `generateMetadata()` metadata object or a separate server component. Article JSON-LD: use `content.data.title` for `headline`, `content.data.createdDate` for `datePublished`, `content.data.lastUpdated` for `dateModified`. Builder.io\'s `createdDate` and `lastUpdated` are Unix timestamps in milliseconds — convert via `new Date(content.data.createdDate).toISOString()`. All JSON-LD must be in server-rendered HTML, not in Builder\'s client-side component hydration — verify with the JavaScript rendering gap check.
Is the Builder.io SEO audit free?
Yes. The complete audit is free with no signup and no email gate. Enter the URL of your frontend consuming the Builder.io API — the audit crawls the rendered HTML as Googlebot would. No Builder.io API keys, Space ID, or admin access needed. Works with Builder.io across all SDK integrations: Next.js, Nuxt, SvelteKit, Astro, Angular, React, and custom integrations. Paid DeepSEOAnalysis plans add saved report history, scheduled monitoring, larger crawls (up to 1,000 pages), and white-label agency reporting.