How to get trained in Adobe AEM

After posting my last article, Jumping into Adobe AEM Development,  I received an email from a reader with a very valid question: What training resources are available for those who are not a Partner and wanting to learn more about AEM?

Great question. This short answer is, there are training options available for non-partners. But first let me tell you what’s available as a Solution Partner:

As a Partner, any contact can utilize the Solution Partner Portal and get:

  • AEM Download (Sandbox available for Business-level Partners and above)
  • Access to the Adobe Demo Hub
  • Access to free subsidized online training (270+ courses)
  • Communications and Updates on Solutions
  • Access to hundreds of assets and collateral
  • Discounts on Adobe Training Services (ATS) courses
  • And more. I personally use the Solution Partner Portal at least once per day.

But if you’re not with an approved Partner, or don’t work for a customer who has purchased AEM, then your access and resources would be very limited.

This is a huge issue since the AEM community does not have access to experienced, fresh talent.   A company can’t hire someone unless they’ve been part of the Partner ecosystem at some point and has learned the product through that means. So, the company has to blindly hire the smartest developer they can find, cross their fingers, and put them through either on-the-job training or formal Adobe Training Services training – all while the project finish line never moves. Just throwing them onto a project without AEM exposure means cutting corners or understanding AEM development best practices.  So, if your organization it not a Partner, get enrolled now. I can’t stress that enough.

If you’re not a Partner, the main resource would be Adobe Training Services, where you can pay for AEM Courses and get hands-on experience with the Solution and, during the course period, get hands on access to the software. I would recommend using Adobe Training Services as the primary training resource to learn more about AEM. You can also access – for free – the Adobe Experience Manager Developer Site, which contains lots of helpful information on AEM.

 

 

Jumping into Adobe AEM Development

Got a great note from a reader asking advice on whether he should dive in and learn AEM development:

I am a User Interface Designer with minor Front End Developer skills. I was recently hired by a major eye wear company  for the sole purpose of migrating a version of one of their Native Apps over to AEM. I have no real experience with AEM Development, but I am a fast learner and I already have the AEM portal experience mastered (along with creating articles, collections, layouts, etc..)

My question is: Do you think it is viable/worth it for me to dive head first into AEM Development and try to learn the various languages/frameworks necessary to be able to customize an AEM app? Or is it something that would take years to understand and a complete change of my skillset?

Kind of a random question, I know… but your article was great so I thought I would reach out for advice. Thank you Mr. Meehan!

Seemingly Unrelated Story Time…

I grew up in a stereotypical, plain vanilla American suburban neighborhood – complete with station wagons, paper routes, penny loafers, Golden Retrievers, the works. There was even a pool up the street where you could pay 50 cents to swim all day.

I didn’t know how to swim until I was almost 11 years old, and none of my friends knew it. I could have won an Oscar for Best Actor for the work I did in that pool. I had all the individual skills to be a swimmer, but I never put the pieces together. If I held onto the side of the pool with my hands, I could float and kick my legs – no problem. When I was away from the wall, I would just walk with my feet touching the ground and paddle my arms so it looked like I was swimming. But, once I felt the curvature of the floor move towards the deep end, I would turn around and go back the other way because I knew I would be over my head.

Fast forward one muggy Michigan summer…

Somehow my ultra-conservative mom made friends with a backwoods, country bumpkin lady who had just moved to Michigan from a little town in West Virginia. She looked exactly like Willie Nelson in drag. I can’t remember her name, but it was one of those redneck stoner names where two regular stoner names are mashed together to make it even more rednecky, like “Misty Sue” or “Deena Jo”.

One day we were at the pool (or “swimmin’ hole”, as she called it) and she saw me walking in the shallow end, paddling my arms. She knew I couldn’t swim and I knew she was about to expose my secret as soon as she finished the Virginia Slim cigarette dangling from her lips. She paced back and forth along side the pool like a junkyard dog, watching me. I knew I was doomed, so I stayed in the pool until my hands and feet were as pruned as a crocodile’s scrotum. Yeah, I said it.

When I finally got out of the water, she took the last drag from her cigarette, dropped it into a can of warm Shasta soda and shook it.  Ssssssssssst.  She slowly walked over to me, grabbed me, then said, “Ya know what time it is, hound dog? …It’s swimmin‘ time!”

At first,  I thought it was weird that someone just called me, “hound dog”. Then, I was relieved because I thought she was going to say, “Hey, everyone! This kid can’t swim!”  Then, I realized “swimmin‘ time” loosely translated to “throw me in the deep end”.

I tried to scurry away and break her grip, but I couldn’t. She had me a crazy country wrestling hold I called, The Full Willie Nelson.  The more I struggled, the more my sunburned back scraped across the stubble on her leathery legs, until I could take no more. I conceded and wilted onto the scalding concrete.

fullnelson

She lifted me up over her head and threw me into the middle of the diving pool, which was the deepest part of the L-shaped pool. I sunk down about three feet, panicked, and started kicking my legs until I got to the surface of the water. I kept kicking my legs and flailing my arms and realized that the more I kicked and flailed, the more I moved closer to the safety of the wall. “Holy sh*t, I’m swimming!,” I thought.

I spent the rest of the day jumping into the deep end on my own and swimming back to the wall, all while Mrs. Willie Nelson smoked and watched from the edge.

Get to the Point…

Adobe is selling the hell out of AEM right now. Internally, they simply don’t have the capacity to keep up with all of the services opportunities to stand up, develop, and manage the platform, so they’re turning to partners to do the work.  If you’re hiring, you’ll be lucky to find a single AEM developer just sitting on the bench. And, if you do, they won’t be there long.

Time to jump in!

You already have some of the individual skills required to start developing in AEM. Most importantly, you’re already familiar with the tool. If you do this now, you can ride the demand wave for the next four years or so until the market evens out.  By then, you’ll be leading your own team.

The easiest way to learn it is to just jump in and do it.  Learning to code is the easy part. Since Sightly, we’ve enabled most of our front-end developers to create templates and components on their own without much back end coding. Template and component development is a good place to start.

Don’t get over your head!

You don’t need formal training,  but you do need a mentor who can take a look at your design and code to make sure you’re developing using best practices. Most of the clean-up work we do is directly related to a client hiring a development team who oversold their capabilities, didn’t follow any standards, and left the client with a non-scalable platform littered with hundreds of templates and components. Hundreds!  Don’t be that guy.  If you don’t have a mentor, get involved in the Adobe developer forums. There are some incredibly talented men and women on there who were once in your shoes and will answer any question you have.

I’ll leave you with a quote from Helen Hayes, whoever that is…

“The expert at anything was once a beginner.”

-Someone named Helen Hayes

Jump in the pool, hound dog. It’s swimmin’ time.

 

Stone Soup: A Recipe for Personalization Using the Adobe Marketing Cloud

This article is the first in a series I’m devoting to the idea of multi-solution architecture; that is, the ability to understand how (and when) to connect other solutions of the Adobe Marketing Cloud to help drive consistent, personalized experiences across channels and devices.

If you think you’re just going to be an AEM architect in this “digital disruption” age, you’re wrong. Over 70 of my clients own two or more solutions of the Adobe Marketing Cloud and that’s growing quickly.  Clients now expect agencies and system integrators understand how these work together to meet the marketing goals of their business.

Adobe has a specific role within their organization dedicated to the strategy, planning, and implementation of multiple solutions called the “Multi-solution Architect” (MSA).  It’s such a rare skill-set in the marketplace that within the walls of Adobe themselves, there are currently only around 15 MSAs worldwide.  This capacity gap means opportunity for you, if you take advantage of it now.

The job description for the Adobe MSA calls for expertise in at least one solution of the Marketing Cloud and (for starters), and the ability to at least ‘whiteboard’ which solution should be used in conjunction with one another to target and personalize their experience. So, it doesn’t mean you have to know ‘how to push the button’ on every solution – you just have to know there’s a button to push and delegate to your solution experts when appropriate.

Here are a few key characteristics of the MSA from the job description:

  • Leverage your deep knowledge of digital marketing technology to align overall solution architecture to digital marketing strategy.
  • Become a trusted advisor for Customers in planning, implementing and optimizing cross-channel digital marketing initiatives, creating a digital-first culture and mastering digital operational excellence.
  • Lead customers to place a stronger emphasis on targeting and optimization, apply data-driven insights to fine tune planning and improve digital ROI.

I learn best by example, so I’ll use the solutions of the Adobe Marketing Cloud as ingredients in the cupboard to make a recipe for personalization following the theme of an old folktale called, “Stone Soup”. This will help you start to understand the what/where/when the other solutions besides AEM should be used and get you on a path to becoming a Multi-solution Architect.

Stone Soup

Some travelers come to a village, carrying nothing more than an empty cooking pot. Upon their arrival, the villagers are unwilling to share any of their food stores with the hungry travelers. Then the travelers go to a stream and fill the pot with water, drop a large stone in it, and place it over a fire. One of the villagers becomes curious and asks what they are doing. The travelers answer that they are making “stone soup”, which tastes wonderful, although it still needs a little bit of garnish to improve the flavor, which they are missing. The villager does not mind parting with a few carrots to help them out, so that gets added to the soup. Another villager walks by, inquiring about the pot, and the travelers again mention their stone soup which has not reached its full potential yet. The villager hands them a little bit of seasoning to help them out. More and more villagers walk by, each adding another ingredient. Finally, the stone (being inedible) is removed from the pot, and a delicious and nourishing pot of soup is enjoyed by all. Although the travelers have thus tricked the villagers into sharing their food with them, they have successfully transformed it into a tasty and nutritious meal which they share with the donors.

Wikipedia, the source of all truth

Let’s imagine instead that this fantastic Stone Soup we want to create is a fully-personalized, cross-channel marketing ecosystem and the ingredients the villagers supply are solutions from the Adobe Marketing Cloud.  If we add the ingredients one-by-one, what personalization can we do? How could each ingredient make the soup even better? Let’s get cooking…

Adobe Experience Manager (AEM)

Adobe Experience Manager is a comprehensive content management solution for building websites, mobile apps and forms

aem

Our first ingredient we’ll add is Adobe Experience Manager, since this is the one you know best. On it’s own, we can do some basic personalization by leveraging the internal Context Hub, which is the new-and-improved version of the Client Context.  Think of the Context Hub as a place to store key/value pairs of known information about the visitor –  First name: Brad.  Last name: Meehan.  Sex: Sure.  Out-of-the-box we have basic information we can key-off of like geolocation and device data, and you can integrate with other services to populate the Context Hub on your own with other useful, custom data.

Once you have the key/value pairs in the Context Hub, you create Audiences and Offers to display unique content for those segments using the values as ‘traits’.  But, if you want to show content for a specific audience that is not at first identifiable using these values, you would have to ask the user “self-identify” who they are.

By self-identification, I mean asking the user to explicitly select their path for a particular journey, like a Choose Your Own Adventure book.  “Are you a new or existing customer?” or “Would you like to buy or sell a car?”  This works for a small number of audiences, but I’ve seen instances where a client wanted the user to select from a list of over 80 roles to show them different user journeys for each.

Now, if we were cooking in Gordon Ramsey’s kitchen, this is where he would say, “Self-identify? Are you f**king kidding me?!”   But you, our trusted MSA, would say, “There’s another way…”

grady_hellskitchen_post

Key Points to Remember:

  • Create, manage, and publish content specific to their audiences
  • Basic personalization functionality using Context Hub
  • How do I know the audience segment if values in Context Hub aren’t available or useful? The user must self-identify.
  • Licensing determined by number of instances

Adobe Analytics

Analytics is the industry-leading solution for collecting, organizing, analyzing and reporting

aa

What if the user’s behavior could determine their audience instead of asking them explicitly?  If the visitor is reading articles about “How much car can I afford?”, viewing current auto loan rates and trade-in values, and using payment calculators, they are likely a buyer versus a seller.  We can use these behavioral decisions to determine the audience they belong to and use this to drive personalization. We can also identify outliers, or anomalies in what we thought our visitors would do, versus what they actually do on our site and adjust our strategy ad hoc.

The key here is to be nimble. A human’s attention span is now less than that of a goldfish. You must determine their audience segment quickly and show them relevant content, or the user will look elsewhere.   I usually give a site about three clicks to find (or progress to) what I’m looking for before I use bad words in front of my kids and bailout completely.  Don’t judge.

I heard a weird statistic that said, ‘of the Adobe customers that own only one solution, 95% own Analytics.’

Analytics is an essential solution of the Adobe Marketing Cloud. I can use my Analytics data to identify high-performing content or assets, and share that with Adobe Target to show offers in AEM using the native Target/AEM integration.

Key Points to Remember:

  • Use it to learn about the visitor as they browse
  • Display personalized content based on their behaviors
  • Determine user segment quickly or user will bounce
  • You can use this on your existing web properties and mobile apps, regardless of the technology platform you used to build it.
  • Licensing determined by number of server calls per year

Adobe Target

Adobe Target is personalization solution that makes it easy to identify your best content through tests that are easy to execute. So you can deliver the right experience to the right customer.

atAdobe Target is the ingredient we’ll add to our pot to automate personalization using things like click-stream data from Analytics without having to manually manage or create targeting rules.  This fully-automates our behavioral-driven personalization effort using AEM and Analytics alone, solving the goldfish issue. Here’s a video demo of the Automated Personalization feature of Target.  Kinda bad-ass.

AEM 6.2 has native integration with Target and you can use audiences you create in Target to drive Offers authored in AEM.  Conversely, you can use Target (regardless of the presence of AEM) to author experiences using Target’s Visual Experience Composer.

You can also do A/B and Multi-Variate Testing (MVT) to determine and promote the best content for our Offers. Meaning, you can test combinations of copy, images, colors, etc to see which perform best to help drive conversions.

Key Points to Remember:

  • Automate personalization
  • Create “personalized” content using native Target to AEM integration
  • Perform A/B and Multivariate Testing. See what’s working.
  • Promote best performing combinations of content.
  • You can use this with your existing web properties and mobile apps, regardless of the technology platform you used to build it.
  • Licensing determined by page views per year

Adobe Audience Manager

Adobe Audience Manager is a data management platform that helps build unique audience profiles to identify the most valuable segments and use them across any digital channel

aamWhat if instead of driving personalization from learned behaviors, you could instead identify and target an audience before they ever did a single thing on the site?  Or if you could show the visitor a relevant, targeted offer in a search results page? Audience Manager is Adobe’s Data Management Platform that allows you to use first, second, and third-party data to create audiences and do cool things.

First party data is information you already own about your visitor, such as if they are an existing customer or not.  But, unlike data stored in your CRM system, data in Audience Manager is anonymized so there’s no Personally Identifiable Information (PII) to secure, manage, or audit.  But, visitors are still uniquely identifiable and have a single Marketing Cloud ID to share across solutions so we are marketing consistently to the customer regardless of channel.

Second-party data is information you get from your partners (like Facebook or Twitter) who are willing to share (or sell) data about the visitor. You can’t argue with how powerful leveraging data about our visitors from their social channels would be to increase conversions.  Want to sell more IROC-Zs? Pull in an audience of everyone who “likes” Metallica, Zubaz pants, and Oakley Blade sunglasses. Done.

Companies like Axciom and Datalogix have thousands of data points for nearly every person in the United States that you could purchase and use to target offers. This is third-party data. And you can mix and match traits to create very specific audiences you want to target and use them not only on your website, but in targeted ad buys.

Did you know in the Datalogix data set, there are 18,708,763 people who can instantly be identified as “soccer moms”?  This would have significantly helped me on my Match.com profile.

Key Points to Remember:

  • Integrate with anonymized first, second, and third-party data
  • Identify the user before they see the page
  • No PII data to manage
  • Share audiences across solutions
  • Licensing determined by number of impressions

Adobe Campaign

Adobe Campaign is a cross-channel campaign management tool that helps you improve and personalize campaigns across all of your media.

ac

Adobe Campaign is the ingredient we’ll use to nurture our clients and prospects via email and real-time in-app messaging with the ultimate goal of keeping them away from the unsubscribe button.

How many times have you received an email from a brand that had nothing to do with you? Or it wasn’t timely and therefore irrelevant to your needs? Just this week I received a message from a company with shipping tracking information for a product I received over a month ago. That would have been great to have weeks ago.

Messaging should not only be timely, but be relevant and consistent to the recipient depending on where they are in their user journey:

  • Learn more about our Wine of the Month Club!
  • Thank you for joining our Wine of the Month Club!
  • New Wine of the Month Club members only! Buy one get one free!
  • Thank you for your wine order! Your 20 bottles are on the way!
  • Track your shipping!
  • Back so soon?
  • Rough day at the office?

You get the point.

Unlike Audience Manager, Adobe Campaign does contain PII data about our customers, but  you can share anonymized audiences with other solutions of the Adobe Marketing Cloud.

Key Points to Remember:

  • Use first-party CRM data to drive email and in-app messaging.
  • Target and re-target prospects
  • Retain acquired customers
  • Hosted or on-premise options available
  • Licensing determined by number of active emails and number of emails sent per year

Adobe Media Optimizer

Adobe Media Optimizer is a media optimization solution that helps you forecast the best mix of search, display and social ads based on your budget. It also automates the execution of your media plan.

amo

I recently saw a banner ad for my personal bank with a call-to-action to “Open a Checking Account Today!” – even though I’ve had a checking account with them for the past 15 years!  Since I’m  in market for a used car, I’ve searched numerous times for used car loans in Kansas City and never have I seen my bank’s loan offering in a banner ad or paid search. Either they’re the only bank in Kansas City that doesn’t loan money or they missed a great opportunity to place a relevant ad touting their lending products. What ingredient could we add to our Stone Soup to solve this dilemma in the future? Media Optimizer.

Media Optimizer used in combination with the bank’s first-party data could have been used to identify me (and the other 360,000+ existing customers) and change the messaging to suit my needs. They could have bid, purchased, and displayed targeted ads in real-time specific to my needs.  

Key Points to Remember:

  • Bid, purchase, and display target ads in real-time
  • Show media to targeted customers only
  • Licensing determined by spend for display, search and social

Adobe Social

Adobe Social is a social management platform that ties every piece of data to your bottom line. Beyond just the likes and follows, manage the deep relationship between your customers’ sentiments and your business goals.

asCommunication is a two-way street and it is important to understand what people are saying about a brand, not just what the brand is saying to them. Adobe Social is used not only to create and manage social posts on various social channels and listen to the conversations to identify trends or new opportunities. This used with other tools of the Adobe Marketing Cloud could offer countless opportunities to proved relevant offers and content.

Recently a client wanted to know if it was possible to monitor social channels for trending conversations then use the most frequently mentioned keywords to automatically promote related content on their own website.  For example, say the chatter on the web suddenly increased around Volkswagen’s emissions scandal. Your large, reputable auto manufacturing client has numerous articles on their website about recent awards for legitimately having the lowest emission vehicles on the road.  Probably something you’d want to share now!  You could use Social, Analytics, (Target), and AEM to solve this complex, but useful use case.

Key Points to Remember:

  • Manage social engagement
  • Surface trends on Social channels
  • Target content for trending topics

Adobe Primetime

Not a freaking clue.

Key Points to Remember:

I got nothin’.

Conclusion

So, there’s your first taste of Stone Soup. Part two will dive deeper into multi-solution architecture with real world examples of poor digital experiences and how to solve them. Stay tuned.

Please send consulting questions to brad@bradmeehan.com

Guest Post: Reusing Tabs or Fields in Multiple Dialogs

I recently wrote an article called, “Reusing Tabs or Fields From an Existing Dialog” showing the benefits and steps to include previously defined dialog tabs and fields in another component for reuse. The article gained some traction when it was shared on one of Adobe’s thought leadership sites.  It turns out,  however, I may have taken a Joe Gunchy (Read more about Joe here. He’s an idiot) approach to this solution myself and did not consider what would happen if the parent tab or widget changed and how it would affect its children.

Tomek Niedźwiedź, an experienced AEM developer from the WPP Adobe Alliance partner Cognifide, commented on the post with a very smart and elegant solution to avoid the pitfall of reusing parts of a dialog when the parent itself is changed.  I thought it would be a great guest post, and asked Tomek if he would like to contribute his solution. Below is a wonderfully written article which not only fits nicely into the type of technical content I want to share, but it’s also written in a voice that reads like a great story, which makes learning the material fun.

Please enjoy his article and be sure to thank him in the comments for sharing his expertise and his time!

-Brad Meehan

Reusing Tabs or Fields in Multiple Dialogs

Hi, my name is Tomek and I’m a Java/AEM developer at Cognifide. I was invited by Brad to write a follow-up on his article about tab and field reuse in AEM dialogs. If you haven’t read the original post and for some reason do not feel like reading the whole thing now, here’s a short recap.

A neat way of avoiding the duplication of widget or tab definitions using the cqinclude pseudo xtype is described. We’re shown how we can use a widget to reference the definition of another piece of content and have the JavaScript responsible for creating and displaying the dialog to authors fetch the relevant content from another place.

We’re shown a working example of a component reusing a field already defined in another component.

There is a Carousel component that has a play speed configuration option which authors can use to set the amount of time, in milliseconds, between slide transitions. A playSpeed widget defined in the component’s dialog is then reused by a new component that happens to require the exact same configuration. Let’s say, for the sake of argument, that the new component shows an animation based on a set of images.

It all works fine when the new component is developed. The widget definition is read properly and the right interface is displayed to the user. Both components work like a charm. Everybody’s happy. But there’s something we’ve done that should be avoided. What is it and what are the consequences?

Months pass and authors realize that they tend to put a lot of text in the slides, often ending up configuring the play speed to be at least several seconds. They’ve grown a bit tired with typing so many digits at a time so they ask the team to change the configuration to use seconds rather than milliseconds. A new developer who has just joined the team grabs the ticket and dives into the carousel code. He discovers the playSpeed setting and happily adjusts the unit in the dialog and the JavaScript behind the carousel itself. He’s not a rookie so he remembers to also write a script to update existing content (every instance of the Carousel component out there) to cater for the different configuration. He pushes the code and enjoys a coffee break. Code gets deployed.

The same afternoon, the team gets messages from disgruntled users. Something about an Animation Component’s configuration being confusing. They’re prompted to set the amount of time in seconds between frames, which doesn’t make sense. Such intervals would just be too long. A bit puzzled, our developer brings up the IDE and opens the code behind the Animation Component. All seems fine. There’s some Java code to load the frames from some place, some perfectly logical JavaScript to handle the animation in the browser. Nothing out of the ordinary. After some time, he looks at the dialog definition and notices the reference to the familiar /libs/foundation/components/carousel/dialog/items/carousel/items/playSpeed.infinity.json

Right, there’s no way the user-friendly hint about the play speed in seconds that he added to the Carousel’s dialog would make sense in this context. This needs to be fixed.

I recently happened to be the new guy on one of my projects so I decided to leave little cautionary comment under the original post. Brad kindly invited me to write a whole guest post on the subject.

There’s a saying often quoted among software developers and I’m not sure who used it originally (according this answer on Stack Overflow, it may have been used for the first time as far back as 1991) but it goes something like this:

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. Code for readability.

Fortunately, I’m not the guy from this quote, nor have I ever worked with anyone fitting this description. In the worst-case scenario, I just write a blog about what I’ve run into. Given my writing skill, this is bad enough for the world so I think there’s no need for violence.

Anyway, the thing wrong with cross-referencing dialogs is that it makes code terse as opposed to concise. We avoided duplication but we fell into the trap of making the code so short as to hide important information.

Let’s see how we can structure a dialog for maximum readability. Think in terms of dependencies.

Here’s what we did. The relationship between the two components is simple but it’s only explicit when you look at Animation. There’s nothing in the Carousel component to tell us that parts of it are reused elsewhere. The only way to find out about this is to perform an explicit search across the entire codebase.

Reusing Tabs or Fields in Multiple Dialogs

Interestingly enough, a lot of, if not the majority of AEM developers are also Java developers. Hardly anyone would structure object-oriented code in a similar way. As Brad rightly noted in the original post, dialogs in AEM are content. When you look at the content tree, you’ll notice that apart from the various pages, configurations, imagery and the like, the repository also contains quite a lot of code (be it JavaScript, JSP, Sightly or even the compiled Java classes forming the OSGi bundles dropped into the install folders). In an AEM application, code is content and content can be code. A developer should be paying as much attention to the content structure and seemingly static data, as in case of the cherished executable code. Dialogs are not an exception.

In Java, most developers would instinctively opt to implement a common interface and extract the common functionality to a separate class. Then use it by means of composition.

Can a similar thing be done with AEM dialogs? Yes it can. The cqinclude widget does not require us to link to a dialog specifically. In general, a path to literally anything that’s capable of returning a properly formatted JSON document should be sufficient. It’s just a piece of content that the dialog will retrieve by means of an AJAX call and use to render the right inputs.

We can easily do something like this:

Reusing Tabs or Fields in Multiple Dialogs(1)

When extracted, documented and placed in the right spot in the content tree, the play speed widget’s definition becomes a lot easier to reason about.

The same pattern can be easily followed in case of tabs, widgets or even arbitrary configuration nodes.

Let’s take a look at another simple, real life example to demonstrate just how flexible we can be with cqinclude.

One of the most commonly used widgets in the Classic UI is the Rich Text Editor. It’s quite powerful and highly configurable. It can appear in various components, in different contexts. Sometimes it will be customized to cater for the specific needs of a component, sometimes the configurations used across components will be very similar but minute details will differ (such as the label or size of the widget or the like). However, regardless of how many distinct components use it, it’s generally a good idea to provide a consistent authoring experience. Reusing configuration nodes can help us maintain a familiar feel across dialogs.

Let’s say that we want every Rich Text to have the same default paste behaviour and available formats and styles. We will define a common configuration in a single place in the components folder. In order to do that, create a node at:

/apps/example/components/commons/richTextSettings

A couple of things to note:

  • a commons node was created in the components folder to keep all common definitions in one place. This is not a commonly-accepted convention but a rather a loose suggestion made for the sake of this example. Feel free to call it otherwise or place it elsewhere, it doesn’t make a difference to AEM. Whatever path can be handled by Sling will be just fine as long as you find it intuitive.
  • the commons node in the example above should not contain a dialog or _cq_editConfig node, otherwise it will show up in the sidekick, which can lead to JavaScript errors when the authoring scripts attempt to load it as a component definition.

Here’s an example definition. As opposed to screenshots from CRXDE, I’m going to use an XML format that the Maven Vault Plugin uses when content is exported to a local file system (usually, to be made part of a codebase and put under version control together with the rest of the code).

In your IDE, you could see a file called richTextSettings.xml sitting under /apps/example/components/commons. Here’s what it might look like:

<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" jcr:primaryType="nt:unstructured">
    <edit jcr:primaryType="nt:unstructured" features="[cut,copy,delete]" defaultPasteMode="plaintext"/>
    <paraformat jcr:primaryType="nt:unstructured" features="*">
        <formats jcr:primaryType="cq:WidgetCollection">
            <p jcr:primaryType="nt:unstructured" tag="p" description="Paragraph"/>
            <h1 jcr:primaryType="nt:unstructured" tag="h1" description="Heading 1"/>
            <h2 jcr:primaryType="nt:unstructured" tag="h2" description="Heading 2"/>
            <h3 jcr:primaryType="nt:unstructured" tag="h3" description="Heading 3"/>
            <h4 jcr:primaryType="nt:unstructured" tag="h4" description="Heading 4"/>
        </formats>
    </paraformat>
    <styles jcr:primaryType="nt:unstructured" features="*">
        <styles jcr:primaryType="cq:WidgetCollection">
            <successButton jcr:primaryType="nt:unstructured" cssName="btn btn-success" text="Success Button"/>
            <defaultButton jcr:primaryType="nt:unstructured" cssName="btn btn-default" text="Default Button"/>
            <infoButton jcr:primaryType="nt:unstructured" cssName="btn btn-info" text="Info Button"/>
            <primaryButton jcr:primaryType="nt:unstructured" cssName="btn btn-primary" text="Primary Button"/>
        </styles>
    </styles>
</jcr:root>

It’s all very simple. Just a number of RTE plugin settings to define available text formats, the paste behaviour and some custom styles, in case if the authors wished to inline some nice looking buttons.

Note that the jcr:nodeType of the node defined here is just nt:unstructured. This can be different if you want to define a tab (cq:Panel) or a widget (cq:Widget).

Here’s how the configuration can be referenced by a Rich Text Edit defined in a component dialog:

<?xml version="1.0"?>
<productDescription jcr:primaryType="cq:Widget" allowBlank="true" fieldLabel="Product Description" name="./productDescription" xtype="richtext">
    <rtePlugins jcr:primaryType="nt:unstructured" path="/apps/example/components/commons/richTextSettings.infinity.json" xtype="cqinclude"/>
</productDescription>

All that the productDescription Rich Text Editor widget requires is a node called rtePlugins containing the right configurations. We can use the cqinclude xtype to reference our central configuration.

It doesn’t matter to the cqinclude if the node being included is of the type nt:unstructured, cq:Panel or cq:Widget. This allows us to flexibly mix pieces of functionality while maintaining the right level of granularity.

At the same time, by keeping this configuration separate, we avoid cross-referencing components. Wherever the common part is used, it is very clear to the developer that it is a shared piece of content and that multiple components may be affected. It’s also easy to find these components by searching for the occurrences of the shared bit’s path across dialogs.

About Tomek Niedźwiedź

Tomek

Tomek is a Java/AEM developer with experience in CQ and AEM projects utilizing both the Cognifide technology stack (Slice, Zen Garden) and out of the box solutions provided by AEM (such as Sightly or Sling Models). A strong believer in the importance of communities and knowledge sharing in the world of software development, he’s an active user of Stack Exchange sites and is part of Cognifide’s internal training team introducing new developers into the basics of AEM development. Eager to go on-site, he works closely with Cognifide’s clients, providing them with technical knowledge and helping overcome their uncertainties.

About the WPP Adobe Alliance

dNWrERU5_400x400The WPP Alliance is a subset of the network’s digital agencies and an Adobe partner in implementing Adobe Marketing Cloud solutions. With a proven track record of collaboration and delivering implementation and marketing services, the WPP Alliance allows clients to leverage the network’s strengths when client needs go beyond the expertise or footprint of a single agency. Included in the WPP   Alliance are VML, Inc, Cognifide, Acceleration, Mirum, KBM Group, DT, and Wunderman.