AEM Shared Content and Component Properties

December 15, 2016 | Brett Birschbach

Coming from the world of Content Management Systems (CMS) built on top of relational databases, the JCR storage system of Adobe Experience Manager was revolutionary to me.  Instead of data and content types being king, the pages themselves are self-contained entities with behavior and layout of individual components bound to the data within the page at runtime.  In many ways, this is a beautiful thing.  Individual pages or even entire sections of sites can be migrated across servers/environments effortlessly via .zip packages and admins can easily track down content errors since content generally lives directly within the page where the error is displayed. The file system-like implementation of the JCR can be very intuitive and lends itself quite well to website content. But not everything is sunshine and roses…

The Problem

As I alluded to before, many popular CMS are built with data and content types as the primary focus. Pages are a result of queries into centralized RDBMS tables that store all of the hero images, promotions, etc.  Sharing content and properties in these types of systems is a no-brainer, as all data is fundamentally structured and accessed in a reusable way.  Not so with AEM and the JCR.  Instances of the same AEM component (a.k.a. content type) are generally authored and stored individually on each page of a site.  In cases where authors wish to use the same content on multiple pages, this can lead to:

  • Excessive copy and paste;
  • Labor-intensive and unmanageable content changes;
  • No reuse of content and properties without custom implementation.

AEM offers up the OOTB “Reference” component as an option for content reuse, but the solution is limited:

  • It is an all or nothing deal: A Reference is an exact copy of the referenced component, i.e., you cannot share a title or background image via the Reference component if you want the body copy to differ.
  • Authors must track down the single “real” version of a component to make changes.
  • If not used carefully, Reference components can create a nasty spider web of content references across a site.

AEM 6.2 introduces Content Fragments, which can also aid in reuse of content in certain situations, but it, too, is not a complete solution.

When our team first encountered this limitation in AEM, frankly we chalked it up to our lack of in-depth knowledge about this topic.  Surely AEM had a standard solution for shared content and shared component properties, right?  Unable to find this “holy grail” in the jungle of AEM documentation, however, we developed a custom solution for what we termed “global properties” on our sites.  Having a workable solution in our pocket, though, we still kept an eye out for the “correct” solution.  But as we chatted with other leading engineers in the AEM space at conferences such as Adobe Summit, seeking “the AEM way,” it became apparent to us that there was none for shared content and properties.

The Solution

Cue our annual hackathon!  A handful of developers banded together to solve this AEM limitation.  Not only did we want to solve this issue for ourselves, but we also wanted to do it in a generic way that could be contributed back to the AEM developer community, so that all of us can focus on delivering real value to our companies and clients.  Our goal for the 1½ day hackathon was to develop a solution that:

  • Ensures consistency of a component's content across an entire site without copy and paste.
  • Allows shared content and properties to be overridden at the individual component instance level when desired.
  • Provides an intuitive, integrated authoring experience with no paradigm shift from OOTB AEM authoring (seamless implementation).
  • Applies universally to all components that define a “shared” properties dialog, with no specialized implementation required by developers.
  • Can be submitted to ACS AEM Commons for use by the AEM community.

As the dust settled and the clamor of the hackathon died down, our development team was able to put a checkmark in the box for all of the above goals, including an “alpha” level pull request to ACS AEM Commons.  Our feature received immediate positive feedback from the maintainers of the repo, further motivating us to polish up the implementation from its 1½ day hackathon birth to “just make it work” into a feature ready for primetime.  Shared Component Properties is now officially available as part of the ACS AEM Commons library.

Features of Shared Component Properties

  • Component-specific “shared” properties can be configured for any component by adding a new “shared properties” dialog.
  • Component-agnostic “global” properties can be configured for any component by adding a new “global properties” dialog.
    • Authors can be allowed to override “global” and/or “shared” property values with “local” values, e.g., a component can share content for 10 instances on a site, but still allow an 11th instance to have unique content.
  • Dialogs for “shared” and “global” properties are configured exactly like the OOTB component properties dialog, meaning:
    • 100% dialog feature parity.
    • No new learning required for implementation.
  • No alteration of existing functionality; instance-level component properties and dialogs are unaffected.
  • Supports both Touch UI and Classic UI.

Example Use Case for Shared Component Properties

Let’s put this into practice for a company that runs a monthly promotion on their website. The company wishes to display the promotion on all pages of the site that use template X or template Y, totaling 50+ unique pages. To reduce the workload and chance of error while executing monthly updates, authors would like to change the promotion on just one page and have all other pages reflect the updates automatically.  Lastly, the marketing group threw a wrench into things (as can be expected) by asking for the ability to tweak the promotion headline on its seasonal “summer” and “winter” pages.

The new Promotion component displays the following items:

  • Background Image;
  • Headline Text;
  • Main Promotion Copy;
  • Brand Logo.

To solve this scenario, let’s start with the Background Image, Headline Text, and Main Promotion Copy.  These three properties would all be implemented in the “shared” properties dialog for the Promotion. This allows an author to specify those values on any one page of the site, all other pages automatically reflecting those values. This simple change of specifying properties as part of the “shared” properties dialog instead of the standard properties dialog puts us 90% of the way to our goal!

Next is the Brand Logo. The Brand Logo could be implemented in the “shared” properties dialog as well, but a brand logo is something that is quite likely universal to multiple components on the site. For that reason, it would be smart to specify the Brand Logo on a “global” properties dialog for the Promotion component. Other components that need a brand logo, such as a Page Footer, can then specify the same Brand Logo “global” property.  In that way, the Brand Logo needs to be set only once for all components on the entire site: 95% complete!

Last is that seemingly tricky requirement from marketing: The ability to change the promotion headline on its two seasonal pages while still allowing all 48+ other pages on the site to use the shared headline. To enable this, the component simply needs to specify the same Headline Text property as declared on the “shared” properties dialog on the standard properties dialog as well. Witty marketing authors can then go to the component on the “summer” and “winter” pages and use the standard dialog to set the headline to “Hurry while this deal is HOT!” and “Get in on this cool deal!” respectively. Leaving the standard dialog value empty on the remainder the site means the rest of the pages continue to use the Headline Text from the “shared” properties dialog. You’re done!

Marketing is happy. Authors are happy. You’re happy.

For more on this topic, check out Brett's Shared Component Properties podcast.