Tag Manager:
Inject the custom scripts remotely through tag manager systems, this will provide better management of tags without changing the code.
GTM(Google Tag Manager) - Refer https://www.albinsblog.com/2018/12/how-to-include-dynamic-custom-scripts-website-gtm.html for details on injecting the custom script through GTM.
AdobeLaunch-Refer https://www.albinsblog.com/2018/12/how-to-include-dynamic-custom-scripts-adobe-launch-aem.html for details on injecting the custom script through Adobe Launch.
AEM Cloud configuration:
This approach uses the custom AEM Cloud Configuration to include the dynamic scripts - header and footer to the website
Define a Cloud configuration to enable the header and footer scripts and attach the cloud configuration to the required websites to inject the custom dynamic scripts.
Steps-
In CRXDE Lite, create a new node under /apps:
Name: utilities
Type: nt:folder
Create 2 new nodes under /apps/utilities:
Name: components
Type: sling:Folder
and
Name: templates
Type: sling:Folder
Right click on /apps/utilities/components, create a new component genericscriptpage
Label - genericscriptpage
Title - genericscriptpage
group - .hiddenSuperType-cq/cloudserviceconfigs/components/configpage
Add the below additional properties
cq:defaultView - html
allowedParents - utilities/templates/genericscript
Remove the default genericscriptpage.jsp and create content.jsp file under /apps/utilities/components/genericscriptpage with the following content
<%@page session="false"
contentType="text/html"
pageEncoding="utf-8"%><%
%><%@taglib prefix="cq" uri="http://www.day.com/taglibs/cq/1.0" %><%
%><cq:defineObjects/>
<div>
<h3>General Script Settings</h3>
<ul>
<li><div class="li-bullet"><strong>Head Script: </strong><br><%= xssAPI.encodeForHTML(properties.get("headScript", "")).replaceAll("\\&\\#xa;","<br>") %></div></li>
<li><div class="li-bullet"><strong>Foot Script: </strong><br><%= xssAPI.encodeForHTML(properties.get("footScript", "")).replaceAll("\\&\\#xa;","<br>") %></div></li>
</ul>
</div>

Create a new node under/apps/utilities/components/genericscriptpage/:
Name: dialog
Type: cq:Dialog
Properties:
title - Generic Script Configuration
xtype - dialog
Create a new node under/apps/utilities/components/genericscriptpage/dialog:
Name: items
Type: cq:WidgetCollection
Create a new node under /apps/utilities/components/genericscriptpage/dialog/items:
Name: panel
Type: cq:Panel
Properties:
title - Script Configuration
xtype - panel
Create a new node under /apps/utilities/components/genericscriptpage/dialog/items/panel:
Name: items
Type: cq:WidgetCollection
Create a new node headScript under /apps/utilities/components/genericscriptpage/dialog/items/panel/items
Name: headScript
Type: cq:widget
Properties:
fieldLabel - Head Script
name - ./headScript
xtype - textarea
Create a new node footScript under /apps/utilities/components/genericscriptpage/dialog/items/panel/items
Name: footScript
Type: cq:widget
Properties:
fieldLabel - Foot Script
name - ./footScript
xtype - textarea
Create a new component genericscript under /apps/utilities/components
Label - genericscript
Title - genericscript
Remove the default file genericscript.jsp, create a file headScript.jsp and add the below content
<%--
--%><%@page session="false"
import="org.apache.sling.api.resource.Resource,
org.apache.sling.api.resource.ValueMap,
org.apache.sling.api.resource.ResourceUtil,
com.day.cq.wcm.webservicesupport.Configuration,
com.day.cq.wcm.webservicesupport.ConfigurationManager" %><%
%><%@taglib prefix="cq" uri="http://www.day.com/taglibs/cq/1.0" %><%
%><cq:defineObjects/><%
String[] services = pageProperties.getInherited("cq:cloudserviceconfigs", new String[]{});
ConfigurationManager cfgMgr = resource.getResourceResolver().adaptTo(ConfigurationManager.class);
if(cfgMgr != null) {
String scriptCode = null;
Configuration cfg = cfgMgr.getConfiguration("generic-script", services);
if(cfg != null) {
scriptCode = cfg.get("headScript", null);
}
if(scriptCode != null) {
%><%= scriptCode %><%
}
}
%>
Create a file footScript.jsp with following content under /apps/utilities/components/genericscript
<%--
--%><%@page session="false"
import="org.apache.sling.api.resource.Resource,
org.apache.sling.api.resource.ValueMap,
org.apache.sling.api.resource.ResourceUtil,
com.day.cq.wcm.webservicesupport.Configuration,
com.day.cq.wcm.webservicesupport.ConfigurationManager" %><%
%><%@taglib prefix="cq" uri="http://www.day.com/taglibs/cq/1.0" %><%
%><cq:defineObjects/><%
String[] services = pageProperties.getInherited("cq:cloudserviceconfigs", new String[]{});
ConfigurationManager cfgMgr = resource.getResourceResolver().adaptTo(ConfigurationManager.class);
if(cfgMgr != null) {
String scriptCode = null;
Configuration cfg = cfgMgr.getConfiguration("generic-script", services);
if(cfg != null) {
scriptCode = cfg.get("footScript", null);
}
if(scriptCode != null) {
%><%= scriptCode %><%
}
}
%>

Create a file servicefooterlibs.jsp under /apps/utilities/cloudserviceconfigs/components/servicelibs(create the folders utilities/cloudserviceconfigs/components/servicelibs under /apps)
<%@page session="false"%>
<%
%><%@include file="/libs/foundation/global.jsp" %><%
%><%@page import="org.apache.sling.api.resource.ResourceResolver,
org.apache.sling.api.resource.ResourceResolverFactory,
com.day.cq.wcm.webservicesupport.ConfigurationManager,
com.day.cq.wcm.webservicesupport.Service,
java.util.ArrayList,
java.util.Comparator,
java.util.Iterator,
java.util.List"%>
<%
String[] servicePaths = pageProperties.getInherited("cq:cloudserviceconfigs", new String[] {});
if (servicePaths.length > 0) {
ResourceResolver resolver = resource.getResourceResolver();
ConfigurationManager cfgMgr = resolver.adaptTo(ConfigurationManager.class);
Iterator<Service> services = cfgMgr.getServices(servicePaths, new Comparator<Service>() {
//sort ascending by inclusionRank
public int compare(Service s1, Service s2) {
return s1.getInclusionRank().compareTo(s2.getInclusionRank());
}
});
// scripts
List<String> libsScripts = new ArrayList<String>();
ResourceResolverFactory resolverFactory = sling.getService(ResourceResolverFactory.class);
try {
ResourceResolver adminResolver=resolverFactory.getAdministrativeResourceResolver(null);// Getting getAdministrativeResourceResolver(null) is not recommended, this will work only in Author. Reterive the resolver through Service User
while (services.hasNext()) {
Service service = services.next();
String defaultScript = getDefaultScript(adminResolver, service.getComponentReference());
if (defaultScript != null) {
libsScripts.add(defaultScript);
}
}
} catch (Exception re) {
log.error("Cannot retrieve scripts for inclusion",re);
}
for (String script : libsScripts) {
%><cq:include script="<%=script%>"/><%
}
}
%>
<%!
/**
* Returns the path to the footScript.jsp script if the script
* can be found. Otherwise <code>null</code> is returned.
*
* @return Full path to footScript.jsp or <code>null</code>
*/
protected String getDefaultScript(ResourceResolver resolver, String componentPath) {
if (componentPath != null) {
Resource compRes = resolver.getResource(componentPath);
Iterator<Resource> it = resolver.listChildren(compRes);
while (it.hasNext()) {
Resource script = it.next();
if ("footScript.jsp".equalsIgnoreCase(script.getName())) {
return script.getPath();
}
}
}
return null;
}
%>
Create a file serviceheaderlibs.jsp under /apps/utilities/cloudserviceconfigs/components/servicelibs
<%@page session="false"%>
<%
%><%@include file="/libs/foundation/global.jsp" %><%
%><%@page import="org.apache.sling.api.resource.ResourceResolver,
org.apache.sling.api.resource.ResourceResolverFactory,
com.day.cq.wcm.webservicesupport.ConfigurationManager,
com.day.cq.wcm.webservicesupport.Service,
java.util.ArrayList,
java.util.Comparator,
java.util.Iterator,
java.util.List"%>
<%
String[] servicePaths = pageProperties.getInherited("cq:cloudserviceconfigs", new String[] {});
if (servicePaths.length > 0) {
ResourceResolver resolver = resource.getResourceResolver();
ConfigurationManager cfgMgr = resolver.adaptTo(ConfigurationManager.class);
Iterator<Service> services = cfgMgr.getServices(servicePaths, new Comparator<Service>() {
//sort ascending by inclusionRank
public int compare(Service s1, Service s2) {
return s1.getInclusionRank().compareTo(s2.getInclusionRank());
}
});
// scripts
List<String> libsScripts = new ArrayList<String>();
ResourceResolverFactory resolverFactory = sling.getService(ResourceResolverFactory.class);
try {
ResourceResolver adminResolver=resolverFactory.getAdministrativeResourceResolver(null);// Getting getAdministrativeResourceResolver(null) is not recommended, this will work only in Author. Reterive the resolver through Service User
while (services.hasNext()) {
Service service = services.next();
String defaultScript = getDefaultScript(adminResolver, service.getComponentReference());
if (defaultScript != null) {
libsScripts.add(defaultScript);
}
}
} catch (Exception re) {
log.error("Cannot retrieve scripts for inclusion",re);
}
for (String script : libsScripts) {
%><cq:include script="<%=script%>"/><%
}
}
%>
<%!
/**
* Returns the path to the headScript.jsp script if the script
* can be found. Otherwise <code>null</code> is returned.
*
* @return Full path to headScript.jsp or <code>null</code>
*/
protected String getDefaultScript(ResourceResolver resolver, String componentPath) {
if (componentPath != null) {
Resource compRes = resolver.getResource(componentPath);
Iterator<Resource> it = resolver.listChildren(compRes);
while (it.hasNext()) {
Resource script = it.next();
if ("headScript.jsp".equalsIgnoreCase(script.getName())) {
return script.getPath();
}
}
}
return null;
}
%>

Create a template genericscript under /apps/utilities/templates
Label - genericscript
title - Generic Script Configuration
description - Generic Script Configuration
resourceType - cq/cloudserviceconfigs/templates/configpage
allowedChildren - utilities/components/genericscriptpage
allowedPaths - /etc/cloudservices/generic-script(/.*)?

Add below properties to /apps/utilities/templates/genericscript/jcr:content
cq:cloudservicename - genericscript
sling:resourceType - /apps/utilities/components/genericscriptpage(modify the existing value)
thumbnailPath - /apps/utilities/templates/genericscript/thumbnail.png

Upload thumbnail.png with required icon under /apps/utilities/templates/genericscript
Create a page with name generic-script under /etc/cloudservices/
Add the below properties to /etc/cloudservices/generic-script/jcr:content
componentReference - utilities/components/genericscript
cq:template - /libs/cq/cloudserviceconfigs/templates/servicepage
jcr:description - Generic Script Configuration
sling:resourceType - cq/cloudserviceconfigs/components/servicepage
thumbnailPath - /apps/utilities/templates/genericscript/thumbnail.png


Create a configuration page(sample-script) under /etc/cloudservices/generic-script



Add the below line to the header file of your page rendering component - this will displays the header script configured in the generic-script cloud configuration to head section
<cq:include script="/apps/utilities/cloudserviceconfigs/components/servicelibs/serviceheaderlibs.jsp"/> - JSP
<sly data-sly-include="/apps/utilities/cloudserviceconfigs/components/servicelibs/serviceheaderlibs.jsp" /> - Sightly HTML

Add the below line to the footer file of your page rendering component - this will displays the footer script configured in the generic-script cloud configuration to the end of body section
<cq:include script="/apps/utilities/cloudserviceconfigs/components/servicelibs/servicefooterlibs.jsp"/> - JSP
<sly data-sly-include="/apps/utilities/cloudserviceconfigs/components/servicelibs/servicefooterlibs.jsp" /> - Sightly HTML

Configure the cloud configuration in parent page properties

Now the website displays the header and footer scripts


AEM Custom Component:
In this approach define a custom component and include that wherever required in the page to inject the custom scripts and html dynamically.
Steps-
Create a new component
Name: OpenHtml
Title: OpenHtml
Group - Add the required component group name e.g We.Retail
Add the below additional properties
allowedParents String[] */parsys
Define Dialog
Right click the component /apps/weretail/components/content/OpenHtml and select Create, Create Node.
Enter the following values:
Name: cq:dialog
Type: nt:unstructured
Add the below properties
jcr:title - Open Html/Script
sling:resourceType - cq/gui/components/authoring/dialog
Click on the following node: /apps/weretail/components/content/OpenHtml/cq:dialog
Right click and select Create, Create Node. Enter the following values:
Name: content
Type: nt:unstructured
Add the below properties
sling:resourceType - granite/ui/components/coral/foundation/fixedcolumns
Click on the following node - /apps/weretail/components/content/OpenHtml/cq:dialog/content
Right click and select Create, Create Node. Enter the following values:
Name: items
Type: nt:unstructured
Click on the following node: /apps/weretail/components/content/OpenHtml/cq:dialog/content/items
Right click and select Create, Create Node. Enter the following values:
Name: column
Type: nt:unstructured
Add the below properties
sling:resourceType - granite/ui/components/coral/foundation/container
Click the following node - /apps/weretail/components/content/OpenHtml/cq:dialog/content/items/column
Right click and select Create, Create Node. Enter the following values:
Name: items
Type: nt:unstructured
Click the following node: /apps/weretail/components/content/OpenHtml/cq:dialog/content/items/column/items
Right click and select Create, Create Node. Enter the following values:
Name:OpenHtml
Type: nt:unstructured
Add the below properties
fieldLabel - Enter the valid Html/Script
fieldDescription - Enter valid html and/or script. Ensure all tags are closed
name - ./openHtml
sling:resourceType - granite/ui/components/foundation/form/textarea
Add the following content into OpenHtml.jsp
<%@include file="/libs/foundation/global.jsp"%>
<%@page
import="org.apache.sling.api.resource.*,
com.day.cq.wcm.api.WCMMode"%>
<%@page session="false" %><%
request.setAttribute("isEdit", WCMMode.fromRequest(slingRequest) == WCMMode.EDIT);
%>
<c:if test="${(isEdit) }">
<p>
Open HTML
</p>
</c:if>
<!-- Open HTML component -->
${properties.openHtml}
<!-- end of Open HTML component -->
Drag and drop the component to the parsys on required website and configure the script - make sure the script/html is valid and all the tags are closed.
In Edit mode the place holder string "Open Html" is displayed


Now the html content and the script is included into the website page


Download(Cloud Configuration and OpenHtml component) - https://sites.google.com/site/albinsblog/blogdata/custom-script-injection-1.0.zip?revision=1
No comments:
Post a Comment
If you have any doubts or questions, please let us know.