by Ursula Johnson


August 30, 2017

We are back with another Rockstar Tip & Trick guest post from Steven Carter, who is a Web Developer for HS2 Solutions, a digital transformation company based in Chicago. Like our other guest bloggers, Steven was a runner up in this year’s AEM Rockstar competition. For more from Steven, connect with him on LinkedIn ( or GitHub (

Link Tag Management for AEM

Links (anchor tags) are a ubiquitous part of any site, and yet as developers, we hardly give them a second thought. We tell the link where we want the user to be directed to next, and that is generally the extent of the consideration needed for them to work properly. On an AEM site, however, there are a few additional dimensions to the thought process that we need to consider. Will this site be internationalized? Does the label for this link need to be translated, or the target address changed for the internationalized version of the page? For example, say you have an external link pointing to, but on the Spanish translated version of your site, should that external link instead be  Should this link be opened in an external window or tab instead of in the current tab? These considerations and more can be addressed easily if a little planning and forethought are put into the way you add links to the page. By adding a custom JSTL tag to resolve links before adding them to our templates, we have been able to exercise considerable control over our links and can add to this functionality even years after the site was initially built.

Fig. 1: Here is an example detailing the usage of our resolveLink tag. The path is passed to the tag, and then the resulting map of properties is returned into a variable. We can then access specific properties, such as the “resolved” link href, label, or the target attribute and place those within the anchor tag.

Getting Started

The first step in managing your links is adding a simple tag that can take a link and “resolve” it, and then use that tag for every link on your site. This tag takes the link address and applies rules and other behaviors to alter the final link. In the next few sections, I’ll give some examples of different alterations we perform to the final link. Before we get into those specific examples, I want to point out that since we pass all of our links through this tag before they are rendered on the final page, we have a lot of control. As an example, let’s say that months after a site was built, we decide the links going to a certain portion of the site should open in a new tab. Instead of returning to the templates and identifying all of the links that point to that section of the site, we can simply add a new rule to our link resolution tag. A quick substring match and we can update the anchor tag target attribute as desired.

Internal vs. External links

One of the first checks we added to our tag was to identify whether the href attribute pointed to an internal (served by our AEM instance) or an external location. Since we would like to keep the user on the site, all external links should be opened in a new tab or window.

Translation of External URLs

One item that is easy to overlook when translating a website is the external websites. As an example, while is the correct domain for English users, your Spanish users should ideally be linked out to It’s also possible that if you’re linking to an external site somewhere, that the paths may completely differ based on the language. Both of these scenarios are easily handled by a link resolution tag.

Automatic Generation of Link Label

For internal links which point back to a page on our internal AEM site, we use the page’s navigation title as the default link label. This prevents the need for a content author to set a label for each link they might add to a page and allows for easier link generation for components that automatically construct a link tree. For sites that are translated, the navigation title will already have been translated, so this is one less item that needs to have a translation added for each language.

Externalizing Paths

In some cases, we want the final path provided from this tag to be externalized. That is, it has the virtual host instead of the internal publish server address. We created our own code to handle the externalizing of these paths to provide us more control over the final path. We also have a Boolean attribute on the resolveLink tag so that we can choose when we want this externalizing code to run, as there are some cases where we may want the path externalized.

Append Extension or Sling Selector

Here’s another case where we have a Boolean attribute added to the resolveLink tag to modify what we’re asking the tag to do for us. In this case, we default the attribute to true, because in most cases we want an extension to be appended to the final path. Now, when the author uses the pathbrowser widget to select a path (which typically only points to the JCR node, and does not supply its own extension) we can add the required extension to the URL. This is also powerful if you have need of custom sling selectors, which can be added to the URL before the extension is appended. The addition of these extensions is another place where our earlier check for internal vs. external links is helpful because extensions should never be added to external URLs.


When using the AEM launches feature, we sometimes wanted to have a little more control over where content was being loaded from. Say for example we have a component that pulls its content from a path, but the content from that path is not included in the launch. With our launch path resolution code, we can verify if the data exists at the launch path and fall back to the base site automatically if the content does not exist there.

Final Thoughts

As with most things in the programming world, you will be rewarded if you plan ahead and are diligent in your implementation. If every link is resolved with a custom tag before being added to your templates, you can exercise a lot of control and simplify fixes and other adjustments you might need at a later time. You could compare this to always using an i18n tag when displaying text on pages, which pays dividends later when you begin to internationalize your site.

All opinions expressed by Steven Carter are his own and not Adobe’s.