Skip to main content

Advanced guide

Shadow DOM and SEO — web components and what crawlers see

How shadow DOM affects what search engines index: open vs closed trees, web components, and pre-rendering strategies for component-heavy sites.

11 min readProcedure: 20 min checklistAdvancedUpdated

Introduction

Web components are increasingly common, especially in design systems that span multiple frontend frameworks. The SEO gotchas come from shadow DOM: crawlers handle the common case well but can miss content in closed shadow roots or in slot projections that are not hydrated.

The four steps below make shadow DOM content reliably indexable.

Step-by-step

How to: Shadow DOM and SEO

  1. 1

    Use open shadow roots (attachShadow({ mode: "open" }))

    Open shadow roots are traversable from the document context. Googlebot and pre-rendering pipelines can walk them and extract content. Closed shadow roots (mode: "closed") are opaque and risk silent indexing failures.

  2. 2

    Project content through <slot> with accessible defaults

    Content passed via <slot> is visible to crawlers. Provide sensible fallback content inside the slot so the component still has indexable text even if the parent forgets to project.

  3. 3

    Include critical SEO content outside the shadow root when possible

    H1 headings, primary body copy, and key structured data should live in the light DOM (regular children) rather than inside a shadow root. This maximizes crawler coverage across engines.

  4. 4

    Pre-render the composed tree to flatten shadow boundaries

    Pre-rendering captures the rendered HTML after shadow composition. The captured snapshot is regular flat HTML — no shadow boundaries — which removes all indexing uncertainty in a single step.

    components/product-card.ts
    typescript
    import { html, LitElement } from "lit";
    import { customElement } from "lit/decorators.js";
    @customElement("product-card")
    export class ProductCard extends LitElement {
    static shadowRootOptions = { mode: "open" as const };
    render() {
    return html`
    <article>
    <h2><slot name="title">Untitled product</slot></h2>
    <slot name="body">No description available</slot>
    </article>
    `;
    }
    }
FAQ

Questions engineers ask about this guide

Officially undocumented. In practice Googlebot can reach content in closed shadow roots when its Chromium-based WRS renders them, but the reliability is lower than open shadow roots. Avoid closed roots for indexable content.

Non-Chromium readers treat shadow DOM inconsistently. AI crawlers with weaker JavaScript support may miss slot projections entirely. Pre-rendering flattens the tree and resolves this.

Yes, and it is the recommended pattern. Keep primary content in light DOM; use shadow DOM for presentational components. Pre-rendering captures both without distinction.

Editorial trust

Written by ostr.io engineering team · Engineering Team. We build and run pre-rendering infrastructure for more than 200 engineering teams, which is where the numbers and code samples on this page come from.

Last updated . Editorial scope and review policy: About prerender.info.