EDS Blog Blocks Not Crawlable || using document-based authoring via da.live with Fastly CDN. | Community
Skip to main content
Level 1
March 15, 2026
Question

EDS Blog Blocks Not Crawlable || using document-based authoring via da.live with Fastly CDN.

  • March 15, 2026
  • 2 replies
  • 59 views

We are running an EDS implementation using document-based authoring via da.live with Fastly CDN. Our blog section uses three custom blocks:

  • blog-grid — paginated card listing with category filtering, tag colour mapping, and authorDate sorting
  • page-list — sidebar block surfacing the most recent posts for the current category
  • cards — category navigation icons

Content is authored in da.live and published through the standard EDS content bus. The query index URL is resolved dynamically at runtime via /config.json using getConfigValue('query-index').

The Problem:

All three blocks render entirely client-side via JavaScript. On the initial HTTP response, the page shell delivered to crawlers looks like this:

html

<div class="blog-grid">
<div><div>Pagination-limit</div><div>10</div></div>
<div><div>Title</div><div>Category Name</div></div>
<div><div>Guides</div><div>bg-guides</div></div>
</div>

No blog card content. No article titles. No descriptions. No links to individual posts.

Would appreciate any experience or patterns the community has used for SSR at the edge on EDS, particularly around cache invalidation and block hydration timing.

We have a custom EDS blog block rendering entirely client-side via JavaScript, meaning crawlers and AI bots receive an empty HTML shell with no indexable content on initial page load. We are exploring SSR at the edge via a Fastly Edge Compute worker as the recommended fix, but before we commit to a full implementation we would love to hear how others in the community have approached this — specifically around extracting block config from raw HTML in a worker context, whether Edge Dictionary or dynamic /config.json fetch is the preferred pattern for query index URL resolution, how teams are handling cache invalidation when EDS publishes new content, and whether selective hydration using data-ssr detection in decorate() has caused any block lifecycle timing issues in practice.

2 replies

AmitVishwakarma
Community Advisor
Community Advisor
March 15, 2026

HI ​@SumaiyyaSadath 

For Edge Delivery Services today you have to accept one hard fact:

  • EDS itself does not support server‑side rendering. It always serves static, semantic HTML and then decorates it client‑side with JS; there is no built‑in SSR or SSI layer for blocks.
  • See: "Edge Delivery Services does not support server-side rendering or includes… it generates optimized, static markup that can be adjusted on the client side." https://www.aem.live/docs/faq

On top of that, EDS indexing only sees the HTML before JS runs:

  • "The indexing service captures the non-decorated DOM from the initial page load, before JavaScript executes. Content added dynamically won't be indexed by default." https://www.aem.live/docs/faq

Your current blog-grid, page-list, and cards blocks only render via JS, so:

  • EDS' own indexer sees an almost empty <div class="blog-grid">… shell
  • Search engines / AI bots that don't execute JS (or give up early) see the same

The fix is not "turn on SSR in EDS" (it doesn't exist); you either:

  • Refactor the blocks to be progressive enhancement (recommended, supported)
  • Or build custom SSR at the CDN (Fastly Compute@Edge) as your own layer

Below is a short, "this actually works" pattern for both.

 

Option 1 – Supported pattern: make the block HTML-first

Goal: make your blog listing indexable without any edge SSR.

Core idea:

  • Ensure that titles, descriptions, and links to posts are part of the HTML that EDS returns, and use JS only for decoration, filters, sort, pagination.

Concretely:

  • Change the content model for the blog listing:
    • Instead of an almost-empty block:
      <div class="blog-grid">
      <!-- only config rows -->
      </div>
    • Author the actual cards (or at least a simple list of articles) in the document itself, e.g.:
      <div class="blog-grid">
      <div class="blog-grid-config">…</div>
      <ul class="blog-grid-list">
      <li>
      <a href="/blog/post-1">Title 1</a>
      <p>Short description…</p>
      </li>

      </ul>
      </div>
    • The HTML above is what EDS serves in the initial response, so crawlers and AI bots can index it directly.
  • Keep JS for behavior only
    In blocks/blog-grid/blog-grid.js:
    • On decorate(block) do not rebuild the whole DOM.
    • Instead:
      • Read existing <li> items (already indexable content).
      • Apply category filters, tag colors, sorting, pagination purely by manipulating that DOM.
    • That keeps SEO + GEO (LLM) happy while preserving your UX features.
  • Rely on EDS indexing best practices
    • Use the index spreadsheet + query-index for internal queries, but don't rely on JS-only rendering of that data for SEO.
    • The FAQ explicitly calls out that dynamic JS-only content will not be captured by the indexer by default and needs to be combined via index sheets or other means if you want it in query-index.json.
    • See the indexing section of Frequently Asked Questions.https://www.aem.live/docs/faq

This approach is:

  • Fully aligned with EDS' architecture (semantic HTML -> JS decoration)
  • Simple to maintain (no edge code, no custom cache invalidation)
  • Enough for most SEO and AI crawling use cases

Option 2 – Custom SSR at the edge (Fastly Compute@Edge)

If you must keep the blocks fully JS-driven, your architecture (da.live + Fastly) allows you to add your own SSR layer. That's your code, not an Adobe feature, but the pattern you outlined is sound and matches how we prototype edge rendering internally:

  1. Detect when to SSR
    In your Fastly Compute@Edge service:
    • Match URL patterns for blog listing pages.
    • Optionally restrict to crawler/LLM user agents (e.g. Googlebot, GPTBot, PerplexityBot), or use a query param for testing.
  2. Fetch base HTML and query index
    • Fetch the EDS page HTML from .page/.live origin (the "empty" shell).
    • Fetch your query-index JSON at the edge:
    • Either:
      • Store the index base URL in a Fastly Edge Dictionary (recommended – no runtime dependency on /config.json), or
      • In the worker, perform a one-time fetch of /config.json and extract query-index to build the URL.
  3. Server-render the block
    • Parse the HTML (simple string/DOM parser).
    • Locate <div class="blog-grid"> and replace its inner HTML with pre-rendered cards based on the index JSON:
      <div class="blog-grid" data-ssr="true">
      <article class="blog-card">
      <a href="/blog/post-1">Title 1</a>
      <p>Excerpt…</p>
      </article>

      </div>
    • Return this modified HTML as the response for bots (and/or humans).
    • Internal guidance for Fastly edge composition covers exactly this pattern—"composing and serving server-rendered HTML at the edge using content stitched from various backends." See Edge computing (Beta Program) in Release Notes for 2025.12.0 release of Adobe Experience Manager as a Cloud Service. https://experienceleague.adobe.com/en/docs/experience-manager-cloud-service/content/release-notes/release-notes/2025/release-notes-2025-12-0
  4. Handle cache + invalidation
    • Cache the SSR'd HTML at Fastly with a short TTL (e.g. a few minutes) plus stale-while-revalidate, or
    • On EDS publish/index update, call Fastly's purge API (or use soft purges keyed by URL or by a Surrogate-Key that groups all blog listing pages).
  5. Block hydration in the browser
    In blog-grid.js:
    • At the top of decorate(block):
      export default function decorate(block) {
      if (block.dataset.ssr === 'true') {
      // HTML is already fully rendered on the edge.
      // Only wire up interactions: filters, pagination buttons, etc.
      initInteractions(block);
      return;
      }

      // Non-SSR path: fetch query-index and build DOM client-side.
      initClientSideRendering(block);
      }
    • This avoids double-rendering and weird lifecycle issues: SSR HTML remains intact; JS just adds behavior.

This pattern gives you:

  • Static, indexable markup for crawlers and AI
  • Full control over caching/invalidations at Fastly
  • Minimal changes to your existing blocks beyond data-ssr detection

But again, this is custom engineering; Adobe doesn't "turn on SSR" for EDS, and support will treat the Fastly worker as customer-owned logic.

Amit Vishwakarma - Adobe Commerce Champion 2025 | 16x Adobe certified | 4x Adobe SME
Tad_Reeves
Adobe Champion
Adobe Champion
March 30, 2026

Another angle to solving this (in addition to ​@AmitVishwakarma ‘s rather-valid points) is you can look into using Adobe LLM Optimizer to deal with any blocks that are not being crawled.  I did a set of tests on this here: https://blog.arborydigital.com/en/podcast/testing-adobe-llm-optimizer-edge-optimization and leveraging Edge Optimization, you can allow LLMs to crawl the parts of your blog list that aren’t getting picked up.  

The free version of LLM Optimizer lets you do up to 10 URLs with Edge Optimization, which should be enough to at least let you demonstrate a proof of concept.