Skip to content

Breadcrumbs for PLP and PDP#1256

Closed
emipallares wants to merge 7 commits into
integrationfrom
USF-4083
Closed

Breadcrumbs for PLP and PDP#1256
emipallares wants to merge 7 commits into
integrationfrom
USF-4083

Conversation

@emipallares

@emipallares emipallares commented May 21, 2026

Copy link
Copy Markdown
demo.mov

Commerce Breadcrumbs Spike

This PR introduces a new commerce-breadcrumbs block (README) to render breadcrumb navigation on PLP and PDP.

Authoring

authoring

The block reads its content directly from the HTML. Author an <ol> (or <ul>) with one <li> per crumb, in order. Wrap a crumb in <a> to make it a link; leave the last one as plain text for the current page.

<div class="commerce-breadcrumbs">
  <div>
    <div>
      <ol>
        <li><a href="/">Home</a></li>
        <li><a href="/men">Men</a></li>
        <li><a href="/men/clothing">Men's Clothing</a></li>
        <li>Sprite Yoga Strap</li>
      </ol>
    </div>
  </div>
</div>

Renders as:

Home / Men / Men's Clothing / Sprite Yoga Strap

Every crumb (including Home) is provided by the author; the block does not prepend or append anything. The last <li> is always treated as the leaf (current page) and rendered as plain text — its position determines that, not the absence of a link.

Runtime behavior

The block parses the authored <ol> into a flat list of crumbs and renders them through the SDK Breadcrumbs component — ancestors as links, leaf as plain text.

PLP → PDP navigation context

The block also acts as a producer of navigation context. It listens for clicks on any link inside main .product-list-page and persists the full breadcrumb of the current page ([...ancestors, current]) into sessionStorage, keyed to the destination product path.

For example, on PLP /men/clothing the rendered breadcrumb is:

Home / Men / Men's Clothing

When the user clicks a product card, the block writes:

{
  "path": "/products/<product>",
  "trail": [
    { "label": "Home", "url": "/" },
    { "label": "Men", "url": "/men" },
    { "label": "Men's Clothing", "url": "/men/clothing" }
  ]
}

On the PDP, if the stored entry's path matches the current pathname, its trail replaces the authored ancestors, while the leaf still comes from the PDP's own authored HTML:

Home / Men / Men's Clothing / Sprite Yoga Strap

i.e. PDP breadcrumbs reflect the actual path the user took, not just the PDP's own authored trail.

Prerender requirement

For both PLP and PDP, it is recommended that aem-commerce-prerender emits the full breadcrumb <ol> in the block's HTML, including:

  • Home as the first <li>
  • All ancestor categories as linked <li> items
  • The current page label as the last <li> (plain text, no link)

This guarantees deterministic breadcrumbs on direct loads and also enables the contextual override when navigating from PLP (or any page with the breadcrumb block) to PDP. Authors can alternatively define the same <ol> directly in DA on a per-page basis.


Test URLs:

@aem-code-sync

aem-code-sync Bot commented May 21, 2026

Copy link
Copy Markdown

Hello, I'm the AEM Code Sync Bot and I will run some actions to deploy your branch and validate page speed.
In case there are problems, just click a checkbox below to rerun the respective action.

  • Re-run all PSI checks
  • Re-run failed PSI checks
  • Re-sync branch
Commits

…recording

- Introduced a new "Commerce Breadcrumbs" component in component-definition.json and component-models.json.
- Implemented breadcrumb trail recording in header.js and product-list-page.js to enhance navigation tracking.
…pecific product list page

- Changed the event listener to only trigger on clicks within the 'main .product-list-page' element.
- Updated README to reflect the change in the link click context for breadcrumb trail recording.
Comment thread component-definition.json Outdated
Comment thread blocks/commerce-breadcrumbs/commerce-breadcrumbs.js Outdated
Comment thread blocks/commerce-breadcrumbs/commerce-breadcrumbs.js Outdated
Comment thread component-definition.json Outdated
Comment thread blocks/commerce-breadcrumbs/commerce-breadcrumbs.js
@@ -0,0 +1,41 @@
# Commerce Breadcrumbs

Renders a breadcrumb using the SDK `Breadcrumbs` component (`@dropins/tools/components.js`).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this block able to work on any page? Would it be added to a PDP document and a PLP document? Can it be added to other pages?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Drop it in wherever you want a breadcrumb. The PLP→PDP trail propagation is the only "smart" commerce feature, and it gracefully degrades to "just render what the author wrote" everywhere else.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you note this (verbatim?) in this README somewhere?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

Comment thread blocks/commerce-breadcrumbs/commerce-breadcrumbs.js
@aem-code-sync

aem-code-sync Bot commented Jun 2, 2026

Copy link
Copy Markdown
Page Scores Audits Google
📱 / PERFORMANCE A11Y SEO BEST PRACTICES SI FCP LCP TBT CLS PSI
🖥️ / PERFORMANCE A11Y SEO BEST PRACTICES SI FCP LCP TBT CLS PSI

Comment on lines +64 to +66
const anchor = event.target.closest('a');
if (!anchor) return;
const targetPath = new URL(anchor.href).pathname;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think there's a chance this could be wrong. For example, the product-list-page block could be modified to show anchor links elsewhere within the tree under .product-list-page and then clicking those would add to the trail.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first solution I provided was filtering anchors pointing to /products/, but some customer don't have /products/ in their URLs. After reviewing the PLP, I noticed that all interactions use buttons, so I thought it would be simpler to handle it that way.

Do you have an example of a link within the PLP that navigates to a different page?

Anyway, in the worst case scenario, it will store the link path and breadcrumb trail in session storage, but no one will use it, so nothing should really break.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of a link within the PLP that navigates to a different page?

No, I don't have off top of my head. This might just be edge case. I just wanted to raise it so we spent some braincells on it :D

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If required, we could add a class name to the anchors in the PLP dropin so that we can filter them.

…feature, with fallback behavior for other contexts.
@emipallares

Copy link
Copy Markdown
Author

Adding a documentation tutorial based on this implementation here: commerce-docs/microsite-commerce-storefront#928

Closing this for now, but we may reopen it in the future if we decide to provide this solution out of the box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants