Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Customizing data collection with Coremetrics for WebSphere Commerce

Baron Lam (baronlam@ca.ibm.com), Software Developer, IBM, Intel, Microsoft,HP
Photo: Baron Lam
Baron Lam is a Software Developer with the WebSphere Commerce Marketing and Analytics team at the IBM Toronto Lab. Baron joined IBM upon graduation from McMaster University with a Bachelor Degree in Software Engineering and Management in 2005. His current work interests involve buzzwords, such as Web analytics, rich Internet applications, Web 2.0, and scrum agile development.

Summary:  WebSphere® Commerce provides an enhanced Web analytics solution with tight integration with Coremetrics®. Coremetrics is a provider of on-demand Web analytics and precision marketing solutions, offering a Web analytics platform that captures and stores all customer and visitor clickstream activity to build Lifetime Individual Visitor Experience (LIVE) profiles. This integration provides all the necessary data points to give most businesses valuable information they need to operate efficiently. This article describes how you can further customize the data collection system to tailor Coremetrics reports for your specific business.

Date:  10 Jan 2007
Level:  Intermediate

Activity:  2677 views
Comments:  

Introduction

The Coremetrics for WebSphere Commerce solution provides businesses with essential information to track and improve shopper conversion rates, return on investment, and customer behavior. The enhanced Web analytics feature provides all necessary data required to answer many of these vital business questions. However, there is a need to tailor these data points to individual business.

This article details different methods to add, change, or override the dataset that is sent to Coremetrics. In addition, you learn the effects and impact of these changes to your pages in terms of caching and site performance.

This article assumes that the WebSphere Commerce Enhancements have been installed with the Coremetrics feature on WebSphere Commerce v6.0, but the information is also applicable on versions 5.6 and 5.6.1. It is also assumed that you have experience in or have already tagged your store using the Coremetrics tag library for WebSphere Commerce (hereafter referred to as tag library). For more information about Coremetrics and how to configure WebSphere Commerce using Coremetrics, see the Resources section.


Using the extraparms attribute

The tag library is simply a wrapper that generates JavaScript code. As a result, the generated JavaScript adheres to a pre-defined application program interface (API) published by Coremetrics. While the generated data is suitable for most customers, different businesses require different information to run their company effectively. The extraparms attribute allows for this simple extension.

Each tag that is provided with the tag library has an optional extraparms attribute as part of its definition that communicates additional information to Coremetrics as necessary. Note that updating your tags to send new data is not enough - you need to contact Coremetrics and let them know of the changes you are making to the API.

As an example, let’s consider the product tag. Using the tag library, a normal implementation on your Product Display page is <cm:product databean="${productBean}"/>. In turn, this tag generates data, such as product names, SKUs, and category IDs like the following JavaScript example:

cmCreateProductviewTag(null, "FULO-01",
	"White Fabric Roll Arm Chaise", "10004", "10001", "N");

Any information specified as a value for the extraparms attribute is appended to the argument list in the Coremetrics tag output and should be properly escaped JavaScript. If you wish to pass more than one value, separate individual parameters by a comma. Input values are either static or dynamic in nature.

Providing static inputs

In this context, static inputs are those values that don’t require any parsing or processing by the tag library. These inputs can be simple strings, or Java Server Page (JSP) variables that contain a string.

Using the product tag example above, let’s assume you wish Coremetrics to report on which product views had a product that was on sale. To do this, you need a new seventh parameter for the JavaScript cmCreateProducviewTag() function. Also assuming that at a JSP level, you know beforehand whether or not a product is on sale. This could be the case, for example, if you have different WebSphere Commerce views (and JSPs) to display a product like ProductDisplay and SaleProductDisplay. In this scenario, your new tags are <cm:product databean="${productBean}" extraparms="\"no\""/> and <cm:product databean="${productBean}" extraparms="\"yes\""/>,, respectively.

Because there is no parsing or processing done on these input values, the responsibility of using properly escaped JavaScript is left to you. In this example, quotation marks are prefixed with a backslash in the input to extramparms.

Most likely, your site is setup to only use one product details JSP. Within this JSP, you may have logic that calculates whether or not the particular item is on sale and if so, sets the expression language (EL) variable ${onSale} to be "yes" or "no". Your new product tag is <cm:product databean="${productBean}" extraparms="\"${onSale}\""/>.

In both cases above, the generated JavaScript looks like:

cmCreateProductviewTag(null, "FULO-01",
	"White Fabric Roll Arm Chaise", "10004", "10001", "N", "yes");
	

Providing dynamic inputs

The extraparms attribute also allows you to tell the tag library to make a function call on your behalf; this is what we call dynamic inputs. Any parameter given that starts and ends with the $ symbol , $getMethod$, for example, is assumed to be a method name of the databean associated with the particular tag. The tag library executes that method and returns the result as a data point to Coremetrics.

There are a few rules to what methods you can tell the tag library to call:

  1. The method must exist in the databean used with the tag itself. For example, if you are passing in an ItemDataBean to the product tag, the given method must be a method of the ItemDataBean object. Similarly, the shopping cart tag will apply methods to OrderDataBean. For more specifics on what databeans are used, see the documentation for each tag type in the WebSphere Commerce Information Center.
  2. The method must take no arguments.
  3. The result object returned by the method must implement the toString() method because it doesn’t make sense to pass anything but strings to Coremetrics.

By default, product prices aren’t sent to Coremetrics until the item is placed into a shopping cart. Assume that your business wishes to report on the prices of products being viewed because prices change frequently, and you may want to see how they affect product view statistics.

Instead of getting the price value and passing it into the tag as a static value, you can simply have the product tag call getCalculatedPrice() on your databean. Your tag is:

<cm:product databean="${productBean}"
	extraparms="$getCalculatedPrice$"/>
	

Note that there are no brackets as part of the method name. If you wanted to track the product’s sales status and price, you can mix static and dynamic inputs together giving you the following tag:

<cm:product databean="${productBean}"
	extraparms="\"${onSale}\",$getCalculatedPrice$"/>

The final output for Coremetrics is:

cmCreateProductviewTag(null, "FULO-01", "White Fabric Roll Arm Chaise",
	"10004", "10001", "N", "yes", "199.99");
	


Caching considerations

In some cases, your customization may require passing uniform resource locator (URL) parameters from page to page. The problem occurs when your site is taking advantage of the caching capabilities of WebSphere Commerce. Let’s take a look at a sample problem.

By default, the product tag provides the category ID of the product as defined in your store catalog. We recommend using a master catalog for analytics, but there is no reason why you cannot use sales catalogs. The only caveat to using sales catalogs is that in the case where a product or item is categorized in more than one category, the tag library will report on the first category associated with the product or item. Take for example, a “Men’s White T-shirt” that is normally categorized in the T-shirt category. As part of your end-of-month clearance drive, the same men’s T-shirt is also categorized in the Clearance category of your store. On all product views of this T-shirt, the tag library reports that the T-shirt is part of the T-shirt category, regardless of whether or not the user viewed the T-shirt while browsing the Clearance category.

To track this information, update your CategoryDisplay page so that all links to ProductDisplay have the additional cmCategory parameter with the value of the current category. For example, on the T-shirt category display page, a link to the Men’s White T-shirt is /ProductDisplay?productId=10001&cmCategory=Tshirt, and from the Clearance page, /ProductDisplay?productId=10001&cmCategory=Clearance. On your product display page, use the Coremetrics tag:

<cm:product databean="${productBean}"
	extraparms="\"${param.cmCategory}\""/>

Your store’s existing cachespec.xml file contains the following snippet that creates a cache key based off of the productId parameter on ProductDisplay requests:

<cache-entry>
	<class>servlet</class>
	<name>com.ibm.commerce.struts.ECActionServlet.class</name>
	<property name="consume-subfragments">true</property>
	<property name="save-attributes">false</property>
	<cache-id>
		<component id="" type="pathinfo">
			<required>true</required>
			<value>/ProductDisplay</value>
		</component>
		<component id="productId" type="parameter">
			<required>true</required>
		</component>
	</cache-id>
</cache-entry>

By adding the new cmCategory parameter to your links and not updating your cachespec.xml file, the cached page contains the contents of the first page request for the particular product. For example, if the T-shirt above was first viewed by a shopper looking at the clearance items, the JavaScript generated and cached is:

cmCreateProductviewTag(null, "SKU1234", "Men’s White T-shirt",
	"10004", "10001", "N", "Clearance");

As a result, any further requests to the Men’s White T-shirt are categorized as “Clearance”. Even if the cmCategory URL parameter was set to “T-shirt”, it is ignored. In the following sections, we consider various solutions to this problem.

Using page or fragment caching

By adding the new cmCategory parameter to your cache key, the two versions of the product display pages above are properly cached with the appropriate content. Using the full page caching of ProductDisplay, the new cache entry definition looks like the following:

<cache-entry>
	<class>servlet</class>
	<name>com.ibm.commerce.struts.ECActionServlet.class</name>
	<property name="consume-subfragments">true</property>
	<property name="save-attributes">false</property>
	<cache-id>
		<component id="" type="pathinfo">
			<required>true</required>
			<value>/ProductDisplay</value>
		</component>
		<component id="productId" type="parameter">
			<required>true</required>
		</component>
		<component id="cmCategory" type="parameter">
			<required>false</required>
		</component>
	</cache-id>
</cache-entry>

While this change is relatively simple, it may cause your cache to explode. In this example, your cache just doubled in size. Where there was previously one cached page, the system now has two pages saved in the cache. The problem gets worse if many products are cross-categorized many times. If your site doesn’t have many other pages that are cached, or if your system has lots of memory to spare, perhaps doubling or tripling the size of your cache for analytics is acceptable.

The alternative caching strategy is to implement fragment caching on your product display page. A fragment that is cached separately from its parent page allows for different cache keys to be defined. When the page is requested by a browser, all of the individual fragments get assembled together from the cache.

In our example, let’s assume you redesigned your normal ProductDisplay.jsp file so that it includes the /snippets/CachedProductDisplay.jsp file. CachedProductDisplay.jsp is where you instantiate your databean and display all your product data to the user leaving common elements, such as the page header, footer, and navigation in the parent ProductDisplay.jsp page. Your new cachespec.xml now contains:

<cache-entry>
	<class>servlet</class>
	<name>com.ibm.commerce.struts.ECActionServlet.class</name>
	<property name="consume-subfragments">true</property>
	<property name="save-attributes">false</property>
	<cache-id>
		<component id="" type="pathinfo">
			<required>true</required>
			<value>/ProductDisplay</value>
		</component>
		<component id="productId" type="parameter">
			<required>true</required>
		</component>
	</cache-id>
</cache-entry>
<cache-entry>
	<class>servlet</class>
	<name>/snippets/CachedProductDisplay.jsp</name>
	<property name="do-not-consume">true</property>
	<property name="save-attributes">false</property>
	<cache-id>
		<component id="productId" type="parameter">
			<required>true</required>
		</component>
		<component id="cmCategory" type="parameter">
			<required>false</required>
		</component>
	</cache-id>
</cache-entry>

Within CachedProductDisplay.jsp, you also add the Coremetrics product view tag:

<cm:product databean="${productBean}"
	extraparms="\"${param.cmCategory}\""/>

The end result in the cache is one cached page for the parent ProductDisplay.jsp and two versions of CachedProductDisplay.jsp, one containing the “T-shirt” category, and one with “Clearance”. Notice that this doesn’t solve the cache explosion problem that exists with full page caching. In fact, we have more cached entries! Next, we’ll take a look at a solution that doesn’t require modifying your existing caching strategy.

Sidestep caching with JavaScript

There is no reason why you must access URL parameters using a JSP mark-up. JavaScript can easily do the work that we need. By using this new strategy:

  1. There is no need for caching.
  2. Any performance impact for URL parameter lookups is moved off the server and to the client.

The first step to implement the JavaScript solution is to write a helper function. This returns URL parameter values corresponding to the given parameter name. We then set a new JavaScript variable cmCatID with the value of the URL parameter cmCategory. Somewhere on your ProductDisplay.jsp, before the Coremetrics tags, add the code below:

<script language="JavaScript">
// getURLParam() assumes URL parameters are name-value-pairs
// A valid URL would be http://domain/page?name1=value1&name2=value2
// Any similar, more (or less) robust function can be substituted here
function getURLParam(name) {
	var pairs = window.location.search.substr(1).split("&");
	for(var i = 0; i < pairs.length; i++) {
		var nvp = pairs[i].split("=");
		if((nvp.length == 2) && (nvp[0] == name)) {
			return nvp[1];
		}
	}
	return "";
}
	var cmCatID = getURLParam("cmCategory");
</script>

Now you can call the product tag using a static input, <cm:product databean="${productBean}" extraparms="cmCatID"/>. This produces the following JavaScript:

cmCreateProductviewTag(null, "SKU1234", "Men’s White T-shirt",
	"10004", "10001", "N", cmCatID);

Since cmCatID was defined as a JavaScript variable and the browser executes JavaScript sequentially on the page, the cmCreateProductviewTag() function has no problems using the variable. Notice how you don’t need to escape quote the value to extraparms. By design, the tag library forces you to JavaScript escape all your static inputs unless the input itself is JavaScript, such as in this scenario.


Conclusion

This article showed how to customize features of the Coremetrics tag library for WebSphere Commerce so you can alter the default data collected by Coremetrics. To gather some types of data, you may need to pass data from page to page using URL parameters, which has consequences to dynamic caching. You learned what the potential problem areas are and how to work around them. Armed with this knowledge, you can leverage the power of Coremetrics to gain valuable information about your customers and business.


Resources

About the author

Photo: Baron Lam

Baron Lam is a Software Developer with the WebSphere Commerce Marketing and Analytics team at the IBM Toronto Lab. Baron joined IBM upon graduation from McMaster University with a Bachelor Degree in Software Engineering and Management in 2005. His current work interests involve buzzwords, such as Web analytics, rich Internet applications, Web 2.0, and scrum agile development.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere
ArticleID=187716
ArticleTitle=Customizing data collection with Coremetrics for WebSphere Commerce
publish-date=01102007
author1-email=baronlam@ca.ibm.com
author1-email-cc=dwu@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers