Skip to content

AEM Commerce Prerender

The AEM Commerce Prerender solution lets your Edge Delivery ServicesAdobe's hosting and delivery infrastructure that turns authored documents into fast HTML pages served from servers close to the shopper. You push code to GitHub; Edge Delivery Services builds and publishes automatically. Commerce Storefront serve complete product page HTML to search engines and AI crawlers before JavaScript runs. This can improve SEO rankings and make your product catalog readable by large language models (LLMs) and other AI systems.

  1. Deploy the App BuilderAdobe's serverless platform for building and deploying cloud-native apps. The AEM Commerce Prerender app runs on App Builder — it polls your catalog on a schedule, generates product page HTML, and publishes it to Edge Delivery Services. app first, because your storefront integration depends on the HTML it generates. The app runs in Adobe’s cloud on a schedule, polling your product catalog and generating HTML for each product.

  2. The app publishes that HTML to Edge Delivery Services as overlayA complete HTML file that Edge Delivery Services serves at a specific page URL before any JavaScript runs. The prerender app generates one HTML file per product and registers it with Edge Delivery Services, so crawlers and shoppers receive full page content instantly. content, where it becomes part of the initial page HTML served to visitors.

  3. Your product-details block adds interactive features to the prerendered HTML using the product detail page (PDP) drop-inNPM packages that provide core Commerce storefront features such as cart, checkout, product details, and account flows..

By default, Adobe Commerce on Edge Delivery Services renders product information with client-side JavaScript, which limits discoverability for search engines and AI systems that don’t run JavaScript. Edge Delivery Services has no built-in server-side rendering, so the prerender solution is the closest equivalent. Prerendering generates complete HTML — including structured data — and publishes it via the Bring Your Own Markup (BYOM) API before any page is requested. Structured data is machine-readable product information embedded in the HTML, so search engines can read product details without running JavaScript.

  • Enhanced SEO: Complete HTML for search engines improves indexing and rankings.
  • AI-readable catalog: AI systems can read structured markup to understand and recommend your products.
  • Content appears immediately: Prerendered product content is visible while interactive drop-ins finish loading.
  • Faster first load: Pages start displaying content before JavaScript finishes running.
  • Automated updates: Monitors the product catalog and updates markup when products change.

To implement the prerender solution, you’ll work in two repositories. Follow these steps in order:

Loading diagram...
Complete implementation workflow showing the step-by-step process for setting up prerendered product pages in your storefront.

Before implementing the prerender solution, verify you have:

  • Adobe Developer Console access with “Developer” role for your organization
  • App Builder workspace (Stage and Production workspaces recommended)
  • AEM Admin API access for your Edge Delivery Services project (see AEM Admin API documentation)
  • Adobe Commerce instance with Catalog ServiceAdobe's fast, read-only GraphQL API for product data. Drop-ins call it instead of core Commerce GraphQL for product pages, search results, and category listings — up to ten times faster. configured and operational

Your Edge Delivery Services Commerce Storefront must be:

  • Node.js (current LTS version) installed locally
  • Adobe I/O CLI (@adobe/aio-cli) installed globally
  • Git for cloning the prerender repository
  • Familiarity with JavaScript, Handlebars templates, and GraphQL

The three steps in “How it works” describe the high-level flow. The steps below show how the prerender system carries out that process on a schedule in the background:

  1. The store admin manages products in Adobe Commerce.
  2. The prerender system detects product changes.
  3. The prerender system renders pages with semantic markup.
  4. The prerender system publishes the pages via the AEM Admin API.
  5. The prerender system updates the sitemap via the AEM Admin API.
  6. Shoppers access the prerendered product details pages.

The diagram below shows how data moves through each stage, from the store admin’s product update to the shopper’s product page.

Loading diagram...
High-level workflow showing how product data flows from Store Admin through the prerender system to deliver Product Details Pages to Store Customers.

The solution consists of these components:

  • App Builder Actions: Handle product fetching, change detection, and markup generation.
  • Scheduled Triggers: Invoke actions on a configurable schedule to keep content synchronized.
  • Catalog Service Integration: Queries product data from your Adobe Commerce backend.
  • AEM Admin API: Publishes generated markup to your Edge Delivery Services project.
  • Storage Layer: Maintains product state and generated markup in App Builder storage.
  • Management UI: Provides a web interface for monitoring, configuration, and troubleshooting.

The diagram below shows how these components connect and work together to generate and serve prerendered product pages.

Loading diagram...
Complete architecture showing App Builder actions, content management, and how prerendered and dynamic content are delivered to consumers.

The prerender solution publishes everything Catalog Service returns, without filtering by product status, visibility, or stock level. A product gets prerendered when Catalog Service includes it in search results and it has a valid URL key.

The prerender system does not have a draft mode. It renders every product that Catalog Service returns, regardless of whether that product is enabled, visible, or in stock. Whether a draft or inactive product appears in the prerendered site therefore depends entirely on your Commerce and Catalog Service configuration — not on any filtering in the prerender system.

You can also preview the product template itself — the BYOM template document that provides the page structure for all product pages. Open it in Document Authoring (DA), Universal Editor (UE), or another supported editor, with a defaultSku configured to review the layout and content before any products go live.

Products become live on your storefront only when they have been prerendered and published to Edge Delivery Services. The prerender system runs two coordinated polling actions:

  • fetch-all-products — runs every 60 minutes to discover new products in the catalog
  • check-product-changes — runs every 5 minutes to detect changes, render updated markup, and publish product pages

To schedule when a product goes live, control when it becomes visible in Catalog Service. When the product appears in Catalog Service search results, the fetch-all-products action discovers it within 60 minutes and the check-product-changes action publishes it within 5 minutes of discovery.

See the aem-commerce-prerender repository for details on configuring polling intervals in app.config.yaml.

When a product is removed from Catalog Service — because it was disabled, deleted, or its visibility changed — the mark-up-clean-up action removes it from the published storefront. This action runs every 60 minutes and works by comparing the list of currently published product pages against current Catalog Service results: any product in the published index that is no longer returned by Catalog Service is unpublished and deleted.

For faster, event-driven removal, you can build custom instrumentation that observes product changes in Commerce and calls the Edge Delivery Services unpublish API directly. The AEM Admin API unpublish endpoint accepts a resource path and immediately removes it from your live site.

The AEM Commerce Prerender repository has complete installation instructions. The steps below cover the key configuration values for your deployment.

  1. Clone the repository and install dependencies:

    git clone https://github.com/adobe-rnd/aem-commerce-prerender.git
    cd aem-commerce-prerender
    npm install
  2. Run the setup wizard to generate your .env configuration:

    npm run setup

    The wizard prompts for your App Builder workspace selection and Adobe I/O authentication.

  3. Configure environment variables in the generated .env file with your storefront-specific values:

    VariableDescriptionExample
    ORGYour GitHub organization or usernameadobe
    SITEYour AEM site/repository nameyour-storefront
    CONTENT_URLYour AEM content URL (auto-populated by setup wizard)https://main--your-storefront--adobe.aem.live
    STORE_URLYour Commerce store URL (auto-populated by setup wizard)https://main--your-storefront--adobe.aem.live
    PRODUCTS_TEMPLATEURL for the product template page (auto-populated by setup wizard)https://main--your-storefront--adobe.aem.live/products/default
    PRODUCT_PAGE_URL_FORMATURL pattern for product pages (auto-populated by setup wizard). Supports tokens: {locale}, {urlKey}, {sku}/{locale}/products/{urlKey}
    LOCALESComma-separated list of locales (for example, en-us,en-gb,fr-fr) or empty for non-localized sitesen-us,fr-fr
    AEM_ADMIN_API_AUTH_TOKENLong-lived authentication token for AEM Admin API (valid for 1 year). The setup wizard exchanges your temporary token for this automatically.your-admin-token-here
  4. Obtain required credentials:

    • AEM Admin API token: To obtain your token:

      1. Log in to the AEM Admin API (select the link from your preferred Identity Provider, where links suffixed by “_sa” let you pick a specific account instead of the one currently logged in)
      2. Once redirected to the JSON response, open your browser’s Developer Tools (F12)
      3. Go to the Application tab (Chrome) or Storage tab (Firefox)
      4. Under Cookies, find and copy the value of the auth_token cookie
      5. Paste that token in the setup wizard textarea (the setup wizard exchanges your temporary token for a long-lived token automatically)
    • App Builder credentials: To configure the credentials:

      1. Go to the Adobe Developer Console
      2. Open your project and navigate to the workspace you want to use (Stage or Production)
      3. Click Download All in the top-right to download the App Builder configuration file (a .json file)
      4. Run aio app use <file_name> in the root directory of your prerender project to activate the credentials
    • Commerce credentials (Adobe Commerce as a Cloud Service): Access your Commerce Admin → System → Services → Commerce Services Connector for environment and API configuration

    • Commerce credentials (Adobe Commerce Optimizer): Configure your Commerce backend connection according to your deployment type. See the Storefront configuration documentation for details on configuring Optimizer headers and endpoints.

  5. Deploy to App Builder:

    npm run deploy

    This deploys all actions and schedules to your selected workspace (Stage or Production).

  6. Test the deployment:

    • Manually invoke actions using the Management UI or via CLI commands:
      # Fetch all products from Catalog Service and store them
      aio rt action invoke aem-commerce-ssg/fetch-all-products
      # Check for product changes and generate markup
      aio rt action invoke aem-commerce-ssg/check-product-changes
      # Clean up and unpublish deleted products
      aio rt action invoke aem-commerce-ssg/mark-up-clean-up
    • Verify product markup generation for sample SKUs
    • Check that pages publish successfully to your AEM project
  7. Enable automated synchronization:

    • Use the Management UI to start the change detector
    • Configure polling intervals in the app.config.yaml file (default: checks for changes every 5 minutes)
    • Monitor the product index to verify continuous updates

After deployment, access the web-based Management UI to monitor and control your prerender deployment. Configure the UI with your App Builder workspace credentials before deployment-specific data appears.

The Management UI provides:

  • Monitoring capabilities to view published products and track the product index
  • Change detector controls to start, stop, and configure scheduled product polling
  • Markup preview to view generated HTML for product pages before publication
  • Logs and activations for debugging App Builder action executions
  • Storage management to trigger manual product operations and manage App Builder file storage
  • Configuration settings to review environment variables and deployment parameters

You configure access and authentication during the initial deployment. See the repository documentation for details.

With the App Builder app deployed, you’ve completed the first repository. Now modify your Commerce boilerplate — the second repository — so product pages can read and enhance the prerendered HTML the app publishes.

The prerender solution involves two separate codebases that work together:

  1. The aem-commerce-prerender repository (App Builder app)

    • This is the repository you cloned, configured, and deployed in the previous section
    • Runs as a serverless application in Adobe App Builder
    • Generates prerendered HTML and publishes it to your Edge Delivery Services site
    • Operates independently as a background process
  2. Your storefront repository (Commerce boilerplate)

    • Your customer-facing website code
    • Built on the Commerce boilerplate
    • Needs code changes to read and use the prerendered HTML
    • You’ll make the integration changes in this repository.

The prerender app and your storefront meet at each product page URL.

The prerender app saves generated HTML in App Builder storage. The AEM Admin API tells Edge Delivery Services where to find those files so they can be served as an overlay: ready-made HTML at the same address as your product pages (for example, /products/acme-widget/sku123). When a shopper or search crawler opens that URL, Edge Delivery Services returns the prerendered HTML first, so product names, images, and descriptions appear without waiting for JavaScript.

After the page loads, your storefront JavaScript runs and replaces that static HTML with the interactive product detail page (PDP) drop-in. Shoppers then see live prices, stock, and add-to-cart. Use lowercase SKUs in your product URLs because the drop-in reads the SKU from the <meta name="sku"> tag (which preserves the original casing) rather than from the URL. See URL format and SKU handling below.

Loading diagram...
Two-repository architecture showing how the App Builder prerender app publishes HTML that your storefront code consumes and enhances for visitors.

How prerendered HTML reaches your storefront

Section titled “How prerendered HTML reaches your storefront”

The prerendered HTML flows from the App Builder app to your storefront through App Builder storage and Edge Delivery Services overlay configuration:

  1. The App Builder app generates complete HTML files with prerendered product markup.
  2. The App Builder app saves those HTML files to its own file storage.
  3. The AEM Admin API configures the link to the App Builder file storage as an overlay in your Edge Delivery Services configuration.
  4. The AEM Admin API updates your sitemap to include the new and updated product pages.
  5. Edge Delivery Services serves the prerendered HTML from the overlay when product page URLs are requested.

The Commerce Prerender app uses App Builder file storage and Edge Delivery Services overlay configuration. It does not use events to trigger updates. Each time the App Builder app detects a product change and generates HTML, it saves the HTML to App Builder storage and configures the overlay link via the AEM Admin API. When the overlay is configured, the prerendered HTML is served at the product URLs automatically. The storefront needs no additional fetching or configuration.

How the storefront serves prerendered HTML

Section titled “How the storefront serves prerendered HTML”

When a visitor requests a product page URL (for example, /products/acme-widget/sku123), Edge Delivery Services serves the prerendered HTML as the actual page. The HTML already contains the product-details block populated with prerendered content. Your storefront doesn’t fetch it separately.

  1. Request arrives → Edge Delivery Services receives the URL request
  2. HTML served → Edge Delivery Services returns the prerendered HTML file (published by the App Builder app)
  3. Page loads → The browser displays the page with prerendered content (crawlers stop here)
  4. JavaScript executes → Your storefront code runs
  5. Enhancement → The product-details block’s decorate() function replaces the static HTML with the interactive PDP drop-in, which fetches live prices, stock, and add-to-cart from Commerce APIs

This process is called progressive enhancementAn approach where a page starts as complete, readable HTML and JavaScript upgrades it to an interactive experience when it runs. Shoppers with JavaScript get live prices, stock, and add-to-cart. Crawlers and shoppers without JavaScript still see all the product information from the prerendered HTML.: the prerendered HTML is the complete page that everyone sees first. The storefront code reads the page’s existing HTML, extracts the SKU from the meta tag, and upgrades the page to a fully interactive experience for shoppers with JavaScript. Crawlers and shoppers without JavaScript always see complete product information from the prerendered HTML.

To integrate prerendered markup with the PDP drop-in, you’ll need to modify the product-details block in your Commerce boilerplate .

The product-details block lives in your boilerplate at:

blocks/product-details/product-details.js

By the time decorate() runs, Edge Delivery Services has already served the prerendered HTML to the browser, so crawlers have read that content before any JavaScript executes. When decorate() runs, it replaces the static block content with the interactive PDP layout.

Your decorate() function should:

  1. Retrieve the SKU: Read the product SKU from the <meta name="sku"> tag. The prerender system stores the original-casing SKU here, so the drop-in gets the correct value even after URL lowercasing.
  2. Mount the PDP drop-in: Call mountImmediately to initialize the PDP with the retrieved SKU.
  3. Replace with PDP layout: Clear the block content and render the interactive PDP containers.
// File location: blocks/product-details/product-details.js
// Import paths are relative to blocks/product-details/product-details.js
import { getProductSku } from '../../scripts/commerce.js';
import { initializers } from '@dropins/tools/initializer.js';
import { initialize } from '@dropins/storefront-pdp';
import { render as productRenderer } from '@dropins/storefront-pdp/render.js';
import ProductHeader from '@dropins/storefront-pdp/containers/ProductHeader.js';
export default async function decorate(block) {
// Edge Delivery Services served the prerendered HTML before this function ran.
// Crawlers have already read that content. decorate() now replaces it with the interactive layout.
// Step 1: Retrieve the SKU from the meta tag (with URL fallback), then initialize PDP
// getProductSku() reads the SKU from the <meta name="sku"> tag and falls back to URL parsing.
// In template preview mode (Universal Editor or Document Authoring), it reads a defaultSku value from the block config instead.
const sku = getProductSku();
await initializers.mountImmediately(initialize, { sku });
// Step 2: Replace prerendered HTML with interactive composed containers
// Production code builds a layout fragment and renders every region. This sample mounts ProductHeader only.
block.innerHTML = '';
await productRenderer.render(ProductHeader, {})(block);
// ... other rendering code
}

The prerender system generates markup files that match your storefront product URL structure. By default, this uses the format:

/products/{urlKey}/{sku}

The PRODUCT_PAGE_URL_FORMAT can be customized in your .env configuration .

For complete implementation examples, refer to the product-details block in the Commerce boilerplate.

The prerender solution provides these customization options:

CustomizationPurpose and Configuration
TemplatesControl HTML markup structure and styling. By default, markup is handled on the client side at {store_url}/product/default. If the default template is not available, you can edit the template at actions/pdp-renderer/templates/product-details.hbs
Structured DataCustomize JSON-LD schemas in actions/pdp-renderer/ldJson.js to optimize product rich snippets for search engines
GraphQL QueriesExtend product data by modifying GraphQL queries in actions/queries.js . The rendering logic that uses these queries is implemented in the generateProductHtml method in actions/pdp-renderer/render.js
URL PatternsMatch your storefront URL structure by configuring PRODUCT_PAGE_URL_FORMAT in the .env file
Rendering LogicTransform product data before markup generation by implementing custom logic in App Builder actions

For implementation details, see the AEM Commerce Prerender repository , particularly the actions/ directory and repository root for templates and configuration files.

For troubleshooting during development and operations, consult the prerender runbook .

Common issues include:

  • Authentication failures: Verify that your AEM Admin API token is valid (tokens expire after 1 year). To check the token expiration, decode the token using jwt.io or check your AEM project admin panel .

    • Generate a new token if expired (see how to generate a new token ) and update AEM_ADMIN_API_AUTH_TOKEN in your .env file
    • Redeploy with npm run deploy after updating credentials
  • Product not rendering: Check that the product exists in Catalog Service and that the SKU matches.

    • Query the Catalog Service directly using its GraphQL Product API to verify product data
    • Use the Management UI to view the product index and confirm that the SKU is listed
    • Run aio rt activation list to check action logs. For more details, see the runbook
  • Markup not updating: Review the Change Detector logs to ensure scheduled triggers are running.

    • Access the Management UI to verify the change detector status (should show “Running”)
    • Run aio rt activation list to check activation logs. For more details, see the runbook
    • Manually trigger the change detector from the Management UI to test functionality
  • Build error: “Missing or invalid keys in app.config.yaml”: This error occurs when productDependencies entries are missing the required maxVersion property.

    • Error message: must have required property 'maxVersion' in /productDependencies/0
    • Solution: Ensure each entry in the productDependencies array includes maxVersion. Example:
      productDependencies:
      - code: <PRODUCT_CODE>
      minVersion: <MIN_VERSION>
      maxVersion: <MAX_VERSION> # Required field
    • Update your app.config.yaml file and redeploy with npm run deploy
  • Deployment errors: If you encounter 403 errors when running npm run deploy, the aio CLI may be authenticated to the wrong organization. Run aio login --force to re-authenticate and choose the correct organization.

For technical issues or questions during implementation, consult the runbook or contact Adobe Commerce support.