An Experience Fragment is a group of one or more components including content and layout that can be referenced within pages.
An Experience Fragment Master and/or Variant uses:
sling:resourceType
: /libs/cq/experience-fragments/components/xfpage
As there is no /libs/cq/experience-fragments/components/xfpage/xfpage.html
it reverts to
sling:resourceSuperType
: wcm/foundation/components/page
Using the .plain.
selector in the URL, you can access the plain HTML rendition.
This is available from the browser, but its primary purpose is to allow other applications (for example, third party web apps, custom mobile implementations) to access the content of the Experience Fragment directly, using only the URL.
The plain HTML rendition adds the protocol, host and context path to paths that are:
of the type: src
, href
, or action
or end with: -src
, or -href
For example:
.../brooklyn-coat/master.plain.html
Links always reference the publish instance. They are intended to be consumed by third parties, so the link will always be called from the publish instance, not the author.
The plain rendition selector uses a transformer as opposed to additional scripts; the Sling Rewriter is used as the transformer. This is configured at
/libs/experience-fragments/config/rewriter/experiencefragments
The HTML rendition is generated using the Sling Rewriter Pipelines. The pipeline is defined at /libs/experience-fragments/config/rewriter/experiencefragments
. The HTML Transformer supports the following options:
allowedCssClasses
allowedTags
It is recommended to configure the rewriter using an overlay. See Overlays
Social variants can be posted on social media (text and image). In AEM these social variants can contain components; for example, text components, image components.
The image and text for the social post can be taken from any image resource type or text resource type at any level of depth (in either the building block or layout container).
Social variations also allow building blocks and take them into consideration when making social actions (on the publish environment).
To post the correct text and image to the social media network, some conventions need to be respected if you are developing your own customized components.
For this, the following properties must be used:
For extracting the image
fileReference
fileName
For extracting the text
text
Components that do not use this convention are not taken into consideration.
Only editable templates are supported for Experience Fragments.
When developing a new template for Experience Fragments you can follow follow the standard practices for an editable template.
To create an experience fragment template that is detected by the Create Experience Fragment wizard, you must follow one of these rule sets:
Both:
The resource type of the template (the initial node) must inherit from:
cq/experience-fragments/components/xfpage
And the name of the template must begin with:
experience-fragments
This allows users to create experience fragments in /content/experience-fragments as the cq:allowedTemplates
property of this folder includes all the templates that have names beginning with experience-fragment
. Customers can update this property to include their own naming scheme or template locations.
Allowed templates can be configured in the Experience Fragments console.
Developing components for use with/in Experience Fragments follow standard practices.
The only additional configuration is to ensure that the components are allowed on the template, this is achieved with the Content Policy.
In AEM you have the possibility to create Experience Fragments. An Experience Fragment:
One of the use cases for such groups is for embedding content in third party touchpoints, such as Adobe Target.
Using the Export to Target feature, you can:
This feature can be enabled on an author instance of AEM. It requires a valid Adobe Target Configuration, and configurations for the Link Externalizer.
The Link Externalizer is used to determine the correct URLs needed when creating the HTML version of the Target Offer, which is subsequently sent to Adobe Target. This is necessary as Adobe Target requires that all links inside the Target HTML Offer can be publicly accessed; this means that any resources the links reference, and the Experience Fragment itself, must be published before they can be used.
By default, when you construct a Target HTML Offer, a request is sent to a custom Sling selector in AEM. This selector is called .nocloudconfigs.html
. As its name implies, it creates a plain HTML rendering of an Experience Fragment, but does not include cloud configurations (which would be superfluous information).
After you generate the HTML page, the Sling Rewriter pipeline makes modifications to the output:
The html
, head
, and body
elements are replaced with div
elements. The meta
, noscript
and title
elements are removed (they are child elements of the original head
element, and are not considered when this is replaced by the div
element).
This is done to ensure that the HTML Target Offer can be included in Target Activities.
AEM modifies any internal links present in the HTML, so that they point to a published resource.
To determine the links to modify, AEM follows this pattern for attributes of HTML elements:
src
attributeshref
attributes*-src
attributes (like data-src, custom-src, etc)*-href
attributes (like data-href
, custom-href
, img-href
, etc)In most cases, the internal links in the HTML are relative links, but there may be cases when custom components provide full URLs in the HTML. By default, AEM ignores these fully fledged URLs and makes no modifications.
The links in these attributes are run through the AEM Link Externalizer publishLink()
in order to recreate the URL as if it was on a published instance, and as such, publicly available.
When using an out-of-the-box implementation, the process described above should be sufficient to generate the Target Offer from the Experience Fragment and then export it to Adobe Target. However, there are some use cases that are not accounted for in this process; these include:
For these use cases AEM provides the Link Rewriter Provider Interface.
This interface was introduced in AEM 6.5 SP1 (6.5.1.0).
For more complicated cases, not covered by the default, AEM offers the Link Rewriter Provider Interface. This is a ConsumerType
interface that you can implement in your bundles, as a service. It bypasses the modifications AEM performs on internal links of an HTML offer as rendered from an Experience Fragment. This interface allows you to customize the process of rewriting internal HTML links to align with your business needs.
Examples of use cases for implementing this interface as a service include:
sling:alias mechanisms
in place for resourcesThis interface only processes the internal HTML links from the generated Target Offer.
The Link Rewriter Provider Interface ( ExperienceFragmentLinkRewriterProvider
) is as follows:
public interface ExperienceFragmentLinkRewriterProvider {
String rewriteLink(String link, String tag, String attribute);
boolean shouldRewrite(ExperienceFragmentVariation experienceFragment);
int getPriority();
}
To use the interface you first need to create a bundle containing a new service component that implements the Link Rewriter Provider interface.
This service will be used to plug into the Experience Fragment Export to Target rewriting in order to have access to the various links.
For example, ComponentService
:
import com.adobe.cq.xf.ExperienceFragmentLinkRewriterProvider;
import com.adobe.cq.xf.ExperienceFragmentVariation;
import org.osgi.service.component.annotations.Service;
import org.osgi.service.component.annotations.Component;
@Component
@Service
public class GeneralLinkRewriter implements ExperienceFragmentLinkRewriterProvider {
@Override
public String rewriteLink(String link, String tag, String attribute) {
return null;
}
@Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return false;
}
@Override
public int getPriority() {
return 0;
}
}
For the service to work, there are now three methods that need to be implemented inside the service:
[shouldRewrite](#shouldrewrite)
[rewriteLink](#rewritelink)
rewriteLinkExample2
[getPriority](#priorities-getpriority)
You need to indicate to the system whether it needs to rewrite the links when a call is made for Export to Target on a certain Experience Fragment variation. You do this by implementing the method:
shouldRewrite(ExperienceFragmentVariation experienceFragment);
For example:
@Override
public boolean shouldRewrite(ExperienceFragmentVariation experienceFragment) {
return experienceFragment.getPath().equals("/content/experience-fragment/master");
}
This method receives, as a parameter, the Experience Fragment Variation that the Export to Target system is currently rewriting.
In the example above, we would like to rewrite:
links present in src
href
attributes only
for a specific Experience Fragment:
/content/experience-fragment/master
Any other Experience Fragments that pass through the Export to Target system are ignored and not affected by changes implemented in this Service.
For the Experience Fragment variation impacted by the rewriting process, it will then proceed to let the service handle the link rewriting. Everytime a link is encountered in the internal HTML, the following method is invoked:
rewriteLink(String link, String tag, String attribute)
As input, the method receives the parameters:
link
The String
representation of the link that is currently being processed. This is usually a relative URL pointing to the resource on the author instance.
tag
The name of the HTML element that is currently being processed.
attribute
The exact attribute name.
If, for example, the Export to Target system is currently processing this element, you can define CSSInclude
as:
<link rel="stylesheet" href="/etc.clientlibs/foundation/clientlibs/main.css" type="text/css">
The call to the rewriteLink()
method is done using these parameters:
rewriteLink(link="/etc.clientlibs/foundation/clientlibs/main.css", tag="link", attribute="href" )
When you create the service you can make decisions based on the given input, and then rewrite the link accordingly.
For our example, we would like to remove the /etc.clientlibs
part of the URL and add the appropriate external domain. To keep things simple, we will consider that we have access to a Resource Resolver for your service, as in rewriteLinkExample2
:
For more information on how to get a resource resolver through a service user see Service Users in AEM.
private ResourceResolver resolver;
private Externalizer externalizer;
@Override
public String rewriteLink(String link, String tag, String attribute) {
// get the externalizer service
externalizer = resolver.adaptTo(Externalizer.class);
if(externalizer == null) {
// if there was an error, then we do not modify the link
return null;
}
// remove leading /etc.clientlibs from resource link before externalizing
link = link.replaceAll("/etc.clientlibs", "");
// considering that we configured our publish domain, we directly apply the publishLink() method
link = externalizer.publishLink(resolver, link);
return link;
}
If the above method returns null
, then the Export to Target system will leave the link as it is, a relative link to a resource.
It is not uncommon to need several services to cater for different kinds of Experience Fragments, or even to have a Generic Service that handles externalizing and mapping for all Experience Fragments. In these cases, conflicts about which service to use might arise, so AEM provides the possibility to define Priorities for different services. The priorities are specified by using the method:
getPriority()
This method allows the use of several services where the shouldRewrite()
method returns true for the same Experience Fragment. The service that returns the highest number from its getPriority()
method is the service that handles the Experience Fragment Variation.
As an example, you can have a GenericLinkRewriterProvider
that handles the basic mapping for all Experience Fragments and when the shouldRewrite()
method returns true
for all Experience Fragment Variations. For several specific Experience Fragments, you may want special handling, so in this case, you can provide a SpecificLinkRewriterProvider
for which the shouldRewrite()
method returns true only for some Experience Fragment Variations. To make sure that SpecificLinkRewriterProvider
is chosen to handle those Experience Fragment Variations, it must return in its getPriority()
method a higher number than GenericLinkRewriterProvider.