For AI agents: the complete documentation index is available at https://nhanbe.id.vn/llms.txt, the full documentation bundle is available at https://nhanbe.id.vn/llms-full.txt, and this page is available as Markdown at https://nhanbe.id.vn/aem/advanced/experience-fragments.md.

Experience Fragments

16 – Experience Fragments

Target: 3–4 years experienced AEM Developer Syllabus point covered (24, completing it): "CF and XF, and the difference between them." Project domain: a global energy technology company's marketing site.


Before we start — this file exists to complete one comparison

File 15 covered Content Fragments. This one covers Experience Fragments, and more importantly it gives you the full comparison, because your syllabus asks for the difference and that is what actually gets asked.

The sentence to build everything on, repeated from file 15 because it's the answer:

A Content Fragment is content without presentation. An Experience Fragment is presentation with content.

And here's the framing that makes the distinction land, which most candidates miss: they reuse along different axes.

  • A Content Fragment is reused across channels — the same product specification on the website, in the mobile app, in a partner's system.
  • An Experience Fragment is reused across pages — the same promo banner on twenty product pages.

One is about where the content goes. The other is about where the experience appears. Say it that way and the interviewer knows you understand rather than recite.


1. Introduction

1.1 What an Experience Fragment is

An Experience Fragment is a group of components, laid out and styled, saved so it can be reused on many pages.

Concretely: your site header. It's a logo component, a navigation component, a search component and a language selector, arranged in a particular way with particular styling. Every page needs it, and it must be identical everywhere.

Without Experience Fragments, you'd either build it into the page template's structure — which works but means a change requires a developer — or authors would rebuild it per page, which is unmaintainable.

With one, it's authored once as a normal page in the page editor, and referenced wherever it's needed. Change it, and every page using it changes.

1.2 The key structural fact

An Experience Fragment is essentially a page.

It lives under /content/experience-fragments, it's a cq:Page, it's built from a template, and it's edited in the page editor with drag and drop. Everything you know about pages applies — components, policies, templates, publishing, MSM.

Contrast that with a Content Fragment, which is a dam:Asset in the DAM, built from a Content Fragment Model, and edited in a form-like editor.

That single structural difference explains almost all the others:

Because a CF is an asset from a model…Because an XF is a page from a template…
It has typed fieldsIt has components
It has no layoutIt has full layout and styling
It's edited as a formIt's edited in the page editor
It delivers as JSONIt delivers as HTML
It's for channelsIt's for pages

If you can derive the differences from "one is an asset, one is a page," you don't need to memorise the comparison table.

1.3 A real project example to adapt

"We use Experience Fragments for the header, the footer, and reusable promotional blocks. The header and footer are placed in the page template's structure, so they're on every page and authors can't remove them — but they're authored as Experience Fragments, so the content team can change the navigation without a deployment.

The useful part for us is localisation. We have twenty country sites, and the Core Components Experience Fragment component can resolve a localised fragment based on the current page's language — so one component in one template structure serves every country, each getting its own header content.

We also use the plain HTML export for a couple of promotional blocks that a partner embeds on their own site, which means they always get our current version rather than a copy that drifts."

That covers the header/footer pattern, template structure placement, localisation, and the plain HTML export — four things that show real use rather than theory.


2. Core Concepts

2.1 Where they live, and the structure

/content/experience-fragments/
└── energy/
    └── de/
        └── de/
            └── site/
                └── header                 ← the Experience Fragment
                    ├── master             ← a VARIATION (a cq:Page)
                    │   └── jcr:content
                    │       └── root/      ← the actual components
                    └── social             ← another variation

Two levels to notice:

The Experience Fragment itself is a container. Variations live inside it, and each variation is a page with its own component tree.

master is the default variation. You reference a specific variation, not the fragment as a whole — so a reference points at .../header/master.

And the folder structure carries locale, which is what makes localisation work — section 2.4.

2.2 Variations — and how they differ from CF variations

This is a good comparison question, because both CF and XF have "variations" and they mean different things.

Content Fragment variationExperience Fragment variation
What variesThe wordingThe layout and components
ExampleA shorter description for socialA Facebook-formatted version
Stored asA sibling under jcr:content/dataA separate page
Can use a different templateNoYes

An XF variation can use a different template entirely, which is the point — a Facebook variation has different dimensions, different constraints, and genuinely different components from the web variation.

AEM ships templates for social variations. In practice most projects use the web variation and occasionally one more.

2.3 The three ways an Experience Fragment is used

1. Placed on a page by an author. The Experience Fragment component, pointed at a variation. This is the promotional-banner case — an author drops it on twenty pages, and changing the fragment changes all twenty.

2. Placed in a template's structure. This is the header and footer case, and it's the more architecturally interesting one.

From file 03: components in a template's structure appear on every page using that template and are locked so authors can't remove them. Put an Experience Fragment component there, and you get:

  • The header appears on every page — guaranteed by the template structure.
  • Authors can't delete it — it's locked structure.
  • But the header's content is authored in the page editor as an Experience Fragment, so the content team changes navigation without a deployment.

That combination is genuinely useful, and being able to explain why it's better than hardcoding the header in the template is a good answer: the template guarantees presence, the fragment allows change.

3. Exported as plain HTML. .plain.html renders just the fragment's markup, with no page chrome. Used by external systems, email templates, and Adobe Target.

2.4 Localised Experience Fragments — the header/footer pattern

This is the pattern worth understanding, because it connects to file 12 and it's how multi-country sites actually work.

The problem. Twenty country sites all need a header. Structurally identical — logo, navigation, search, language selector. But the content differs: navigation labels are translated, the language selector shows different options, some countries have extra links.

The naive approaches both fail. One shared header means no localisation. Twenty separate references in twenty templates means twenty templates to maintain.

The solution. The Core Components Experience Fragment component supports localisation. You place one component in one template structure, and it resolves the correct localised fragment based on the current page's language.

Page:      /content/energy/de/de/products/transformers
                            ↑ locale

Resolves:  /content/experience-fragments/energy/de/de/site/header/master
                                                 ↑ same locale

One component, one template, twenty localised headers. The structure carries the locale, and the component does the lookup.

And it composes with MSM (file 12). Experience Fragments are pages, so they can be live copies. A country's header can be a live copy of a language master's header — inheriting structure while allowing local exceptions, exactly like site content.

The interview answer:

"The pattern we use is placing an Experience Fragment component in the page template's structure for the header and footer. That gives us two things at once: the template guarantees it's on every page and authors can't remove it, but the content is authored as a fragment in the page editor, so the content team changes navigation without a deployment.

For twenty country sites, the Core Components Experience Fragment component supports localisation — it resolves the fragment matching the current page's locale from the folder structure. So one component in one template serves every country, each getting its own header.

And because Experience Fragments are pages, they work with MSM — a country header can be a live copy of a language master's header, inheriting structure with local exceptions."

2.5 Plain HTML export

.plain.html on an Experience Fragment variation renders just the fragment's markup — no page wrapper, no head, no site chrome.

/content/experience-fragments/energy/de/de/site/promo/master.plain.html

What it's for:

Third-party embedding. A partner site includes your promotional block. They get your current version rather than a copy that drifts out of date.

Email templates. Marketing tools that need HTML.

Adobe Target. Experience Fragments can be exported to Target as offers, for personalisation and testing.

The caching point worth making: it's a normal GET on a path-based URL, so the dispatcher and CDN cache it like any page. Which is good — but it also means a third party may serve a cached version, so invalidation matters when the fragment changes.

And the security point: if you're exposing it to a third party, that URL is public. It should contain nothing that isn't meant to be.

2.6 Can an Experience Fragment contain a Content Fragment?

Yes — and this question is a good test of whether you understand the relationship.

An Experience Fragment is a group of components. One of those components can be a Content Fragment component, rendering a fragment.

A concrete case: a product promo Experience Fragment — heading, image, call-to-action, laid out and styled — where the specification block inside it is rendered from a Content Fragment. The layout is reused across pages; the specification data is reused across channels.

They're not alternatives. They're different axes, and a real page often uses both.

2.7 The full comparison (syllabus point 24)

This is the table the question is asking for.

Content FragmentExperience Fragment
In one lineContent without presentationPresentation with content
ContainsTyped fields — text, number, date, referencesActual components, laid out and styled
Node typedam:Assetcq:Page
Stored at/content/dam/.../content/experience-fragments/...
Created fromA Content Fragment Model (/conf/.../dam/cfm/models)A template (/conf/.../wcm/templates)
Edited inThe Content Fragment editor — form-likeThe page editor — drag and drop
Variations varyThe wordingThe layout, and can use a different template
Delivered asJSON via GraphQL, or rendered by a componentHTML, or plain HTML export
HeadlessYes — the headless building blockPartially — plain HTML only
Reused acrossChannels — web, app, partnerPages
TranslationTranslated as contentTranslated as pages — MSM and language copies
Typical useProduct specifications, articles, structured dataHeader, footer, promo banner, campaign block
Can contain the other?NoYes — an XF can include a CF component

The derivation to remember, because it beats memorising the table:

A Content Fragment is an asset built from a model. An Experience Fragment is a page built from a template. Everything else follows.

2.8 Choosing between them

Use a Content Fragment when:

  • The content is consumed by more than one channel
  • It's structured — distinct typed fields
  • It has its own lifecycle, independent of any page
  • A mobile app or external system needs it as data

Use an Experience Fragment when:

  • You're reusing a laid-out piece of a page across pages
  • The presentation is part of what's being reused
  • It's a header, footer, banner or campaign block
  • A third party needs the rendered HTML

A useful test question: "If I gave this to a mobile app developer, would they want the data or the HTML?" Data means Content Fragment. HTML means Experience Fragment.


3. Internal Working

3.1 How an Experience Fragment renders into a page

graph TD A["Page requested"] --> B["Page renders its components"] B --> C["Experience Fragment component"] C --> D{"Localised, or a<br/>fixed path?"} D -->|"Localised"| E["Resolve the fragment<br/>matching the page's locale"] D -->|"Fixed"| F["Use the configured path"] E --> G["Include the variation's<br/>component tree"] F --> G G --> H["Rendered inline —<br/>part of THIS page's HTML"]

The key consequence is at the bottom: the fragment is rendered inline into the page. It becomes part of that page's HTML, and therefore part of that page's dispatcher cache entry.

Which produces the invalidation problem in the next section.

3.2 The invalidation problem

This is the practical issue with Experience Fragments, and it's the same shape as the derived listing in file 02 and cached GraphQL responses in file 15.

graph TD A["Author changes the header<br/>Experience Fragment"] --> B["Publish the fragment"] B --> C["The fragment is updated on publish ✓"] C --> D{"What about the 5,000 pages<br/>that RENDER it?"} D --> E["Their CACHED HTML still contains<br/>the OLD header"] E --> F["Every page needs invalidating"]

The header is rendered into every page's cached HTML. So publishing the fragment updates the fragment, and every cached page keeps serving the old version until it's invalidated.

For a header or footer that means flushing essentially the whole site. Which is correct, and also a significant operation on a large site — a full cache flush means a burst of cache misses while everything re-renders.

Three things follow, and saying them shows operational awareness:

Header and footer changes are not casual. They invalidate everything.

They should be done at a sensible time, not during peak traffic, because the re-render burst hits publish.

And you need the flush rule to exist. Publishing a fragment doesn't automatically invalidate the pages that include it — something has to make that connection.

3.3 Why an Experience Fragment looks wrong in its own editor

A practical problem worth knowing, because the cause isn't obvious.

The symptom: the header looks correct on a page and completely unstyled when you open the Experience Fragment itself for editing.

The cause: the Experience Fragment is rendered by its own template, and that template's page policy decides which clientlibs load (files 03 and 04). If the XF template doesn't include the site's clientlibs, the fragment renders without the site's CSS.

The fix is aligning the XF template's page policy with the site's, so the fragment previews accurately.

Why it matters beyond aesthetics: authors editing a fragment that doesn't look like the real thing make layout decisions blind. It's a genuine authoring-experience problem, not a cosmetic one.


8. Configuration Examples

8.1 An Experience Fragment component in a template structure

Inside a page template's structure, from file 03:

<root
    jcr:primaryType="nt:unstructured"
    sling:resourceType="wcm/foundation/components/responsivegrid">

    <!-- LOCKED structure component: guaranteed on every page using this
         template, and authors cannot delete it. But the CONTENT is an
         Experience Fragment, so the content team changes navigation
         without a deployment.

         Note: no editable="{Boolean}true" -- deliberately locked. -->
    <header
        jcr:primaryType="nt:unstructured"
        sling:resourceType="energy/components/experiencefragment"
        fragmentVariationPath="/content/experience-fragments/energy/site/header/master"/>

    <container
        jcr:primaryType="nt:unstructured"
        sling:resourceType="wcm/foundation/components/responsivegrid"/>

    <footer
        jcr:primaryType="nt:unstructured"
        sling:resourceType="energy/components/experiencefragment"
        fragmentVariationPath="/content/experience-fragments/energy/site/footer/master"/>

</root>

The fragmentVariationPath points at a variation, not the fragment itself — .../header/master, not .../header.

And for a localised site, the Core Components component resolves the locale-specific fragment from the page's language rather than using a fixed path — so one template serves every country.

8.2 The proxy component

Following the file 02 pattern:

/apps/energy/components/experiencefragment/.content.xml

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
          xmlns:cq="http://www.day.com/jcr/cq/1.0"
          xmlns:jcr="http://www.jcp.org/jcr/1.0"
    jcr:primaryType="cq:Component"
    jcr:title="Experience Fragment"
    componentGroup="Energy - Structure"

    <!-- Proxy the Core Component: we control the version, and we can
         override the HTL later without touching content. Same reasoning
         as file 02. -->
    sling:resourceSuperType="core/wcm/components/experiencefragment/v1/experiencefragment"/>

8.3 The folder structure for localisation

/content/experience-fragments/energy/
├── language-masters/
│   ├── en/site/header/master        ← authored
│   └── de/site/header/master        ← language copy of en
├── de/de/site/header/master         ← LIVE COPY of language-masters/de
├── ch/de/site/header/master         ← LIVE COPY of language-masters/de
└── us/en/site/header/master         ← LIVE COPY of language-masters/en

This mirrors the content structure from file 12 exactly, and that's the point: Experience Fragments are pages, so the same MSM patterns apply. Translate horizontally in the language masters, distribute vertically to the country fragments.

8.4 Plain HTML export

GET /content/experience-fragments/energy/de/de/site/promo/master.plain.html

Returns just the fragment's markup:

<div class="cmp-promo">
    <h2 class="cmp-promo__title">Neue Transformatorenreihe</h2>
    <p class="cmp-promo__text">...</p>
    <a class="cmp-cta cmp-cta--arrow" href="/de/de/products/transformers">Mehr erfahren</a>
</div>

Three things to note:

No page chrome — no <html>, no <head>, no site header.

It's a normal path-based GET, so the dispatcher and CDN cache it like a page. Good for load; means invalidation matters.

The class names are ours. A consumer either includes our clientlib or writes their own styles. If they want it in their design system, they wanted a Content Fragment — story 3.


9. Common Mistakes

The mistakeWhat happensThe fix
Not publishing the fragmentWorks on author, missing on publishXFs have their own publication state
Not planning invalidationPages keep serving the old fragmentA flush rule connecting fragment publish to including pages
Changing a header during peak hoursNear-full cache flush and a re-render burstSchedule it
XF template missing the site's clientlibsAuthors edit against an unstyled previewAlign the XF template's page policy
Referencing the fragment rather than a variationDoesn't resolvePoint at .../master
Using an XF where a CF is rightA consumer gets HTML it can't structureAsk: data or HTML?
Using an XF for a single-use blockIndirection and a publish step for no reuseA component on the page
Hardcoding the header in the templateContent changes need a developerXF in the template structure
Placing the header as initial content instead of structureAuthors can delete itStructure, locked (file 03)
Twenty templates for twenty countriesUnmaintainableOne localised XF component
Exposing internal content in a plain HTML exportIt's a public URLReview what's in the fragment
Assuming a partner wants the HTMLThey may want the dataAsk before building
Inheritance cancelled at page level on a country headerSilently stops receiving all changesFile 12's discipline applies

10. Best Practices

On placement. Header and footer belong in the template structure, locked — guaranteed present, undeletable, but content-authorable.

On localisation. One localised Experience Fragment component rather than one template per country. And use MSM for the fragments themselves, since they're pages.

On invalidation. Plan it before you ship. A header change invalidates everything, so schedule those changes and make sure a flush rule exists connecting fragment publication to including pages.

On previewing. Align the XF template's page policy with the site's, so authors edit against an accurate rendering. This is not cosmetic — they make layout decisions against what they see.

On choosing. Ask whether a consumer wants the data or the HTML. Data is a Content Fragment; HTML is an Experience Fragment. And remember they compose — an XF can contain a CF.

On the plain HTML export. Remember it's a public URL, and agree the styling question with the consumer before shipping rather than after.


11. Debugging Tips

"The fragment doesn't appear on publish." The fragment wasn't published — it has its own publication state, exactly like a Content Fragment. Publishing pages that include it doesn't publish it.

"I changed the fragment and pages show the old version." It's rendered inline, so it's part of every including page's cached HTML. The fragment is updated; the pages are cached. Check whether the flush actually reached those pages.

"The fragment looks unstyled in its own editor." The XF template's page policy doesn't include the site's clientlibs (files 03 and 04).

"The localised fragment isn't resolving." The folder structure under /content/experience-fragments has to mirror the locale structure the component expects. A mismatch means it falls back or finds nothing.

"I can't find what uses this fragment." The References panel — the same tool as for Content Fragments. A fragment doesn't know where it's used, which is the point, so the tooling has to tell you.

ToolAnswers
The References panelWhich pages include this fragment
Fragment publication statusHas it been activated
The XF template's page policyWhich clientlibs load in the editor
Page source on publishIs the old or new fragment markup cached
Private window on publish directlyAnonymous behaviour, without the dispatcher

12. Performance Notes

The fragment renders inline, so it's an include during page render — a small cost, and it becomes part of the page's cache entry.

The real cost is invalidation. A header change invalidates every page. On a large site that's a near-full flush plus a re-render burst on publish, which is a genuine operational event rather than a background one.

Mitigations: schedule those changes outside peak hours, and use the dispatcher's grace period so stale content is served briefly during a flush rather than every request stampeding publish at once.

Many fragments on one page each add an include. That's rarely the bottleneck, but a page assembled from a dozen fragments is doing a dozen includes.

The plain HTML export caches normally, which is good for third-party load — and means the same invalidation thinking applies.


14. Comparison Tables

The full CF vs XF comparison — section 2.7. Learn the derivation rather than the table:

A Content Fragment is an asset built from a model. An Experience Fragment is a page built from a template.

Variations, compared

CF variationXF variation
VariesWordingLayout and components
Stored asA sibling under jcr:content/dataA separate page
Different templateNoYes
ExampleA shorter descriptionA Facebook version

How each is delivered

CFXF
Rendered on a pageBy a componentInline include
To an appJSON via GraphQLNot really
To a third partyGraphQL persisted query.plain.html
To Adobe Target—As an offer

Placement options for an XF

WhereEffect
Author places it on a pageReusable block, author-controlled
In the template structureGuaranteed present, locked — headers and footers
Plain HTML exportExternal consumption

Next topic

17-Sling-Model-Exporter — your syllabus point 26: what the Sling Model Exporter is, how @Exporter turns a model into JSON, the .model.json selector, how it relates to the SPA Editor, and where it fits alongside Content Fragments and GraphQL for headless delivery.


Topic 16 of the AEM Interview Preparation repository. Teaching style, energy-sector project domain.