Monday, November 19, 2012

Report Suites Architecture


I have seen lot of people started thinking about development, when we ask them to integrate site catalyst, Google analytic or urchin in their site, people are immediately jumping into code like how to call JavaScript to record data into site catalyst and how to retrieve site catalyst data etc… but all these things are simple, we can get lot of examples when we read respective SDK’s, but there is another area where we need to put actual attention

What is Report Suite in Site Catalyst?

Every day the omniture system captures thousand of records from web application or website which are integrated with ominture, where exactly all these information stores? These information stores in report suite of site catalyst and we need to pass reportsuiteid for every request

Is one report suite sufficient for entire application?

Before creating new report suite we need to identify what kind of information the client wants to track and what kind of reports he/she wants to generate, without having all these required information in your hand and if you blindly starts then you will be definitely in big mess

Because the report suite supports only 100 events, 75 Traffic variables and 75 conversion variables, what if we want track more than 100 events and if we want to create 76 Traffic variable ?

See the below image,



if we create single report suite for entire Amazon site, then it is very difficult to maintain, if India location head wants to see last one month reports of “Amazon India site” then to generate this report is difficult, we need to apply filters, sometimes the data accuracy problem may occur, and sometimes the events, variables may cross the limit and also we are missing modularization concept here

The solution for this is create new report suite for every location, so that the location head can easily generate reports,  sometimes we may need aggregate data across all locations, we can create global report suite which contain all locations information 


Note : creating report suites is totally depends on how you organize your data , don't forget to get complete information from your client and also the information architects or CMS experts can help on this


Saturday, November 17, 2012

Is it right approach deploying CSS, JavaScript files as part of deployment package in “Content Management System”?


Is it right approach deploying CSS, JavaScript files as part of deployment package in “Content Management System”?

Why,  because I have seen some people who came from traditional web development and no knowledge on CMS trying to deploy css and js files through package and finally mess up entire environment like overriding content of css and js files of content authors

How can we handle this situation, in any cms you can find two types of content one is static content and another one is dynamic content

Dynamic content:

The content which you think it changes frequently need to be handled by content deployment or replication or page activation

Ex: Style sheets, images, text etc…

Normally, the content authors or site admin’s performs this action

Static content:

The content which you think it will not change in future need to be deployed as package such as style sheets, images, JavaScript files etc…
This is the developer job and the developer includes this content into package and deploys into a respective environment

Solution:

You can solve this using several ways one is creating two sets of css files one is for static content and another one is for dynamic content so that if you deploy new package in your CMS environment that t will not disturb dynamic content

Second one is don’t include css and js files in your deployment package keep it in central location which can be accessible by content authors as well as developers
Normally in SharePoint you can do this by placing style sheets in style libray and in CQ5 you can do this by putting in etc/designs folder

Monday, November 5, 2012

Reading data from site catalyst through CQ5

In this article I am going to explain how to read data from site catalyst and display it on CQ5 components

REST api’s :

The omniture exposes REST api to read/write data from site catalyst data source, REST is a lightweight protocol and alternative to Web Services (SOAP, WSDL, etc.), in this I am not going to explain REST based concepts

CQ5:

To connect to site catalyst data source the cq5 has provided cq-analytics.jar file, this jar file is just wrapper of omniture REST api it provide different methods to read data from omniture, using this we can successfully read data from site catalyst from CQ5 environment


POM of cq-analytics jar :

<dependency>
           <groupId>com.day.cq</groupId>
     <artifactId>cq-analytics</artifactId>
           <version>5.4.4</version>
           <scope>provided</scope>
      </dependency>

Code :

The cq5 is provided “SitecatalystWebservice” to connect to site catalyst and there is one more class “Account” we use this entity class to pass account information to site catalyst web service

Account acc = new Account (true, companyName, userName, secret, server);
 
SitecatalystWebservice active = sling.getService(SitecatalystWebservice.class);

String str = active.getReportSuites(acc);

String reports = active.getSuccessEvents(acc,”reportSuiteId”)

The above code returns all success events which are created for “reportSuiteId

CompanyName :

The name is company name which we use to connect to CQ5 omniture site catalyst

Username :

Omniture site catalyst username

Secret:

The secret key is unique for every user we can find this by navigating   “Omniture Site Catalyst”  -> Admin -> Admin Console -> Company

Server :

This is datacenter url we can find this in omniture admin console

Monday, August 13, 2012

Bug in SharePoint 2010

I have created "Survey" activity feed using sharepoint object model but when I try to remove the same I am getting Not Implemented exception

Error Message :

"The method or operation is not implemented."

Code :

removeType = app.ActivityTypes["Survey"];
m_ActivityManager.ActivityApplications[app.ApplicationId].Remove();
//getting The method or operation is not implemented.


if (removeType != null)
{
app.ActivityTypes.Remove(removeType); //getting The method or operation is not implemented.

removeType.ActivityTypeNameLocStringResourceFile = Survey_RFile;
removeType.ActivityTypeNameLocStringName = "Srvey _Feed_Display";
removeType.IsPublished = true;
removeType.IsConsolidated = true;
removeType.Commit();
removeType.Refresh(true);
}

Problem :

Problem is the Remove() method is not implemented

app.ActivityTypes.Remove(removeType);

Resoultion :

Then how can we Remove this?

We can remove the same through sql query but that is not supported by microsoft, if you still want to go ahead and remove you can use below query's

delete [ActivityTemplate] where activitytemplateid > 18
delete [ActivityType] where ApplicationID > 5
delete [ActivityApplication] where ApplicationID > 19

WTF...Do we need to wait until the microsoft releases service pack for this?

Tuesday, June 12, 2012

CQ5 : Creating new page and adding content

In this article, I am going to explain how to create new page and content using SlingHttpRequest Object

<%@page import="com.day.cq.dam.api.Rendition"%>
<%@page import="com.day.cq.dam.api.Asset"%>
<%@page import="org.apache.sling.api.SlingHttpServletRequest"%>
<%@include file="/libs/foundation/global.jsp"%>
<%@page import="org.apache.sling.api.resource.ResourceResolver"%>

<%@page import="com.day.cq.wcm.api.Template"%>

<%
ResourceResolver resolverPage = slingRequest.getResourceResolver();
Resource resPage = resolverPage.getResource("/content/geometrixx");


We are going to read page class, so we need to adapt our Resource to Page.class

Page geoPages = resPage.adaptTo(Page.class);
if(geoPages!=null) {
Resource res2 = resolverPage.getResource(geoPages.getPath());

//The PageManager class helps us to create new pages

PageManager pm = geoPages.getPageManager();

if(pm!=null) {
pm.create("/content/","MspBoxhomeName","/apps/mspbox/templates/contentpage","MspBoxTitle");
Page newPage = pm.getPage("/content/MspHome/");
if(newPage != null)
{
Node newNode = newPage.adaptTo(Node.class);
Node cont = newNode.getNode("jcr:content");
if(newNode != null)
{
cont.addNode("par").setProperty("sling:resourceType","foundation/components/parsys");
Node parNode = cont.getNode("par");
parNode.addNode("image");
Node imageNode = parNode.getNode("image");
imageNode.setProperty("sling:resourceType","foundation/components/image");
imageNode.setProperty("fileReference","/content/dam/geometrixx/shapes/tri_equilateral.png");
parNode.addNode("text");
Node textNode = parNode.getNode("text");
textNode.setProperty("sling:resourceType","foundation/components/text");
textNode.setProperty("text","<p>With at least two equal sides, isoceles is sometimes equilateral and visa versa. Or as the ancient Greeks would say, iso skelos!</p><p></p>");
cont.save();

}
}
}
}
%>

Monday, June 11, 2012

CQ5 : Reading DAM assets

<%@page import="com.day.cq.dam.api.Rendition"%>
<%@page import="com.day.cq.dam.api.Asset"%>
<%@page import="org.apache.sling.api.SlingHttpServletRequest"%>
<%@include file="/libs/foundation/global.jsp"%>

<%@page import="org.apache.sling.api.resource.ResourceResolver"%>

<%

ResourceResolver resolver = slingRequest.getResourceResolver();
Resource res = resolver.getResource("/content/dam/geometrixx/movies");

Node rootNode = res.adaptTo(Node.class);
if(rootNode!=null) {

NodeIterator children = rootNode.getNodes();
while (children.hasNext()) {
Node node = children.nextNode();
if(node != null) {
Resource res1 = resolver.getResource(node.getPath());
Asset as = res1.adaptTo(Asset.class);
String src = "";
String name = "";
String rel = "";
if(as != null) {

Rendition ren = as.getRendition("cq5dam.thumbnail.140.100.png");
src = ren.getPath();
name = as.getName();
rel = as.getPath();
}
out.print("<ul>");
out.print("<li rel=" + rel + "title=" + name + ">");
out.print("<img src=" + src + "></img>");
out.print("</li>");
out.print("</ul>");
}
}
};

%>

CQ5 Reading Node Properties

In CQ5 everything stores in the form of content ( Nodes and Properties ), but while reading content from repository the apache sling framework assumes this is a Resource.Because the sling follows REST based architecture

In this article I am going to explore how to read properties of a Node


<%@page import="org.apache.sling.api.SlingHttpServletRequest"%>
<%@include file="/libs/foundation/global.jsp"%>
<%@page import="org.apache.sling.api.resource.ResourceResolver"%>
<%

By using CRXDE I am going to create component called "PropertyReader" and going to read properties of this component

In CQ5 everything stores in the form of content that means "PropertyReader" component also exists in content repository

the below code will send a request to server and tries to return Resource object if it does not find any resource then it returns Null

We need to use SlingHttpServletRequest object to communicate with CQ5 CRX, here the slingRequest is avariable which is already defined in global.jsp file

ResourceResolver resolver = slingRequest.getResourceResolver();
Resource res = resolver.getResource("/apps/mspbox/components/PropertyReader");

If needed you can adapt a Sling Resource to a JCR Node like below code Node.class, if you are going to read DAM Assets then you need to use Asset.class

Code :

<%@page import="org.apache.sling.api.SlingHttpServletRequest"%>
<%@include file="/libs/foundation/global.jsp"%>
<%@page import="org.apache.sling.api.resource.ResourceResolver"%>
<%

ResourceResolver resolver = slingRequest.getResourceResolver();
Resource res = resolver.getResource("/apps/mspbox/components/PropertyReader");


Accessing a Property :

Node rootNode = res.adaptTo(Node.class);
ValueMap prop = res.adaptTo(ValueMap.class);
String group = prop.get("componentGroup", (String) null);
out.print(group);

Reading all properties :

if(rootNode!=null) {
NodeIterator children = rootNode.getNodes();
while (children.hasNext()) {
Node node = children.nextNode();
if(node != null) {
PropertyIterator pi= node.getProperties();
out.print("<table>");
while (pi.hasNext()) {
Property p = pi.nextProperty();
out.print("<tr><td>");
out.print(p.getName());
out.print(p.getPath());
out.print("</td></tr>");
}
out.print("</table>");
}
}
};
%>

OUTPUT :

General
cq:layout
jcr:createdBy
jcr:created
cq:dialogMode
jcr:primaryType