<?xml version="1.0" encoding="utf-8" ?>
<rss version="0.91">
<!-- RSS generated automatically on Wednesday 19 June 2013, 2:40 -->
	<channel>
		<title>TechPad</title>
		<description>Web analytics implementation hacks for ecommerce and content sites</description>
		<link>http://techpad.co.uk/?utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Main_feed</link>
		<language>en-gb</language>
			<item>
				<title><![CDATA[Returns Management System hacking with Google Analytics]]></title>
				<description><![CDATA[Here's how I used Google Analytics, PHP-GA, Google Docs and the GA Magic Script to create a reporting and analysis system for e-commerce returns management. 

<iframe src="http://www.slideshare.net/slideshow/embed_code/16578618" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen webkitallowfullscreen mozallowfullscreen> </iframe> ]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=249&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_249]]></link>
			</item>
			<item>
				<title><![CDATA[Improving e-commerce analytics with Universal Analytics]]></title>
				<description><![CDATA[My recent presentation from MeasureCamp in London which explained how I'd used the beta version of Universal Analytics and Measurement Protocol to improve the e-commerce analytics in GA. 

<p>
On February 16, 2012, I spoke at MeasureCamp and explained how I'd been using the as-yet-unreleased beta versions of Universal Analytics and Measurement Protocol to improve the default e-commerce functionality of Google Analytics.</p>

<iframe mce_src="http://www.slideshare.net/slideshow/embed_code/16578670" width="427" height="356" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC;border-width:1px 1px 0;margin-bottom:5px" allowfullscreen="" webkitallowfullscreen="" mozallowfullscreen="" src="http://www.slideshare.net/slideshow/embed_code/16578670"> </iframe><div><br> </div><div style="margin-bottom:5px">As it's still in beta, not everything I want to do is possible at the moment, but the GA team has said it now plans to support some of the use cases identified, so hopefully the entire implementation will work as intended when it's finally released.&nbsp;</div><div style="margin-bottom:5px">&nbsp;</div><div style="margin-bottom:5px"><b>Update: </b>March 1, 2013.&nbsp;The GA dev team have now confirmed that the use case of attaching custom dimensions and metrics is now supported, so most of what you see in these slides should now work!&nbsp;</div>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=248&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_248]]></link>
			</item>
			<item>
				<title><![CDATA[Preventing duplicate transactions inflating Google Analytics data]]></title>
				<description><![CDATA[Oddly, Google Analytics doesn't include any kind of protection against a site inadvertently sending the same e-commerce tracking more than once. 

<p>Instead of checking to see whether transaction ABC1234 has already been recorded, it's quite happy to let you send it again, even though it's a duplicate.&nbsp;</p><p>If someone loads reloads the page displaying your e-commerce tracking, and you have no measures in place to prevent the tracking being displayed after a successful send, the data gets to GA again and you'll inflate your figures.</p><p> This is unfortunate. The Google Analytics documentation on e-commerce tracking also fails to warn you of the issue, so I am guessing that many developers make the same mistake.&nbsp;</p>

<h2>How to determine whether your sites are affected&nbsp;</h2>

<p>Some of my sites were affected by this issue because my usually razor-sharp devs had missed this scenario, probably assuming GA had some kind of protection built-in to prevent this. </p><p>To determine which sites were affected I made a custom report. You can <a mce_href="goo.gl/vGdSE" target="_blank" href="http://techpad.co.uk/admin/goo.gl/vGdSE">add it to your account by clicking here</a>. &nbsp;</p><p>It can be used to show whether you're affected by this bug due to your developer failing to prevent the data being sent more than once. </p><p>If you set the reporting period to a wide time period and look at the transactions column, they should all be 1. If any are greater than 1 then your ecommerce tracking is incorrectly configured.&nbsp;</p><p>If your Google Analytics implementation is set up to allow you to zero transactions by re-passing the transaction ID with null values, you'll additionally need to check that the number of transactions doesn't include this extra empty transaction.&nbsp;</p><h2>How to fix your code</h2>

<p>If your sites are affected, your developers will need to modify the e-commerce tracking code on your site to prevent the same data being sent more than once.&nbsp;</p><p><b>1. Record that the transaction has been sent</b></p><p>I overcame this by using a database lookup and a few code and template checks. First, I check the database to see if the transaction ID has been recorded in the database. If it hasn't, I log the transaction ID, then send the data. </p><p>(Obviously the code here is very specific to my particular set-up, which uses the as yet unreleased Measurement Protocol, Data Layers and Universal Analytics, but you should get the idea...)</p><p><img alt="" border="" hspace="" vspace="" width="426" height="170" align="" title="undefined" src="/custom/images/medium/5108ce84d9553.jpg" onmouseover="undefined" onmouseout="undefined"></p><p><b>2. Prevent caching</b></p><p>If you're using a caching system (either page, template or server) then you'll need to make sure you exclude the page which displays your e-commerce tracking. </p><p>We inadvertently broke a site's tracking by installing memcached and forgot to exclude the tracking on this page from the cache...</p><p><b>3. Prevent client-side reloading</b></p><p>On your client-side code you'll need a check to make sure a browser reload doesn't cause the code to be re-displayed. I use the PHP Smarty system for templating on the site I look after, so I've handled it there. </p><p>Again, this is the code to handle Universal Analytics tracking (not the current version of GA) but the principles are the same. </p><p>My e-commerce tracking is contained in a separate template file, but my main analytics template runs a quick check to determine whether it needs to load the e-commerce tracking and a check to determine whether it's been logged/sent already. &nbsp;</p><p>If the data is new and hasn't been sent before, the master template displays the e-commerce tracking. If the data has already been sent, it registers the page view but doesn't reload the e-commerce tracking.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="319" align="" title="undefined" src="/custom/images/medium/5108cff6f3b28.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><br></p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=247&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_247]]></link>
			</item>
			<item>
				<title><![CDATA[Storing user agent strings in Google Analytics]]></title>
				<description><![CDATA[Although Google Analytics uses the user agent string sent by browsers, the string itself isn't available through the interface. However, it can be added with a simple one line hack. 

<div>One of my peers on the Econsultancy MSc course recently asked whether it was possible to track how much traffic a mobile app affiliate had driven to their website using Google Analytics.&nbsp;</div><div><br></div><div>I first suggested that they tag their links with the usual utm_ campaign tracking parameters, however, this wasn't practical as the app and URLs were already set up.&nbsp;</div><div><br></div><div>This made the problem a bit of a challenge. If the app developers had been really considerate, it's a possibility that they might have set a custom user agent string, which is typically used to identify web browsers and operating systems.&nbsp;</div><div><br></div><div>However, even if they did, getting access to this in GA would still be tricky because, unlike some other web analytics tools and good old fashioned log file analysis, Google Analytics conceals the user agent string and it's not available - even in the API tools.&nbsp;</div><div>&nbsp;</div><div><b>User agents</b>&nbsp;</div><div><br></div><div>User agents are set by the browser developers and can be used by web analytics tools to identify the OS, browser and browser version being used.&nbsp;</div><div><br></div><div>Here's a typical example showing Chrome running on Mac OS X: Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/12.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19</div><div><br></div><div>Instead of making these available to the user, Google Analytics parses out the useful data and uses it to group related devices and browsers, allowing it to provide much clearer reports on OS, device and browser usage.&nbsp;</div><div>&nbsp;</div><div><b>Adding user agents to Google Analytics</b>&nbsp;</div><div><br></div><div>In JavaScript, the user agent string is accessible through the navigator.userAgent method, so adding it to Google Analytics is as easy as placing this value in an event.&nbsp;</div><div><br></div><div>_gaq.push(['_trackEvent', 'User agent', escape(navigator.userAgent) , , , true]);</div><div><br></div><div>Since some user agent strings contain quotes that would cause the tracking to break, it's important to use the escape() function to ensure that any potentially dodgy characters are URL encoded before being displayed in the Google Analytics tracking code.&nbsp;</div><div><br></div><div>Once that's in place (before the _gaq.push(['_trackPageview']);) it will start adding all user agent strings to a non-interactive event called User agent.&nbsp;</div><div>&nbsp;</div><div><b>Analysing user agent data in Google Analytics</b>&nbsp;</div><div><br></div><div>You can then sift through these, identify the ones you want to analyse and create advanced segments to monitor them over time.&nbsp;</div><div>&nbsp;</div><div>One slight annoyance is that the Google Analytics interface displays the data in its encoded form, so any spaces become %20. </div><div>&nbsp;</div><div>To me, this feels like a bug and it makes analysing the data a bit more fiddly, but escaping the characters is nonetheless an essential part of feeding more complex data into GA. &nbsp;</div><div>&nbsp;</div><div>Since it sometimes takes Google a little while to update the lists of mobile devices. This hack could also potentially give you a head start in analysing data from mobile devices before GA has updated its parsing code. &nbsp;</div><div>&nbsp;</div><div>I haven't checked how consistently this works, because it relies on the navigator object. Getting the actual HTTP user agent might be more reliable, but obviously needs a server-side solution.&nbsp;</div><div>&nbsp;</div><div>If, you do as I do, and write your GATC in PHP, you can do the same hack by replacing the call to the navigator object with the HTTP user agent stored in the $_SERVER['HTTP_USER_AGENT'] environmental variable.&nbsp;</div><div>&nbsp;</div><div><div><b>A recent usage example</b>&nbsp;</div><div><br></div><div>Analytics expert Rob Kingston (@robkingston) recently asked me whether this hack was showing up data on Windows 8, as he wasn't seeing this in his Google Analytics reports.&nbsp;</div><div>&nbsp;</div><div>The hack does indeed record this. You need to search for Windows%20NT%206.2 because the identifier "Windows NT 6.2" is URL encoded to prevent quotes and things breaking the GATC.&nbsp;</div><div>&nbsp;</div><div>It looks like Google Analytics hasn't yet updated the regular expression it uses to place these user agents in its OS specific segment for Windows 8, so at the moment, this hack is the only way you'll be able to segment these users in GA. &nbsp;</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="280" align="" title="undefined" src="/custom/images/medium/508e2d28e422a.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div></div>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=243&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_243]]></link>
			</item>
			<item>
				<title><![CDATA[Getting started with data mining in R using Rattle]]></title>
				<description><![CDATA[Here is a quick guide to getting started with the Rattle data mining application for the R statistical programming language. 

<div>Rattle is described as "the R Analytical Tool to Learn Easily" and is a cross-platform graphical data mining application written in GTK.&nbsp;</div><div><br></div><div>It can be installed, fairly easily, through R itself via the CRAN repositories and is designed to make data mining a little simpler. Here are the basics steps to follow to get it up and running and to try out some basic data exploration.&nbsp;</div><div><h2>1. Install Rattle</h2></div><div>I'm using the popular RStudio package on a Mac, but it's cross-platform, so you can install it on any platform or do all of this via the command line and the process should be fairly similar.&nbsp;</div><div><br></div><div>To install the Rattle package, go to Packages &gt; Install Packages and enter Rattle. If you've configured RStudio to grab packages directly from a CRAN repository, it should go away and fetch the code it needs.&nbsp;</div><div><h2>2. Configure Rattle</h2></div><div>At this stage, R will have grabbed the Rattle libraries but won't have loaded them, so installation hasn't yet completed. In the R console, type rattle() to load up the Rattle library, then type yes when prompted.&nbsp;</div><div><br></div><div>During the installation process R will fetch any dependencies required, including the GTK libraries used to create the graphical interface. This will look lovely if you're using a version of Linux which natively supports GTK, but it will look fairly grotesque on a Mac.&nbsp;</div><div><br></div><div>When prompted, just say yes to the installation steps and enter your password when required. When it's all done, you'll need to close and re-open RStudio so that R can access everything it needs.&nbsp;</div><div><h2>3. Open Rattle</h2></div><div>To start using Rattle, fire up RStudio and type rattle() in the console. You should now see the GTK-based Rattle application appear in an X11 window.&nbsp;</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="338" align="" title="undefined" mce_src="/custom/images/medium/5007d3c919774.jpg" src="/custom/images/medium/5007d3c919774.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>If you have a rummage around in the interface you'll find the expected toolbar allowing you to open, save, export or execute data, plus a number of tabs which hold the data mining functionality within Rattle.</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="101" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007d6e92348e.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div><b>What the Tabs do:&nbsp;</b></div><div>&nbsp;</div><div><b>Data: </b>The Data tab allows you to select your data source and import from a variety of file formats.</div><div>&nbsp;</div><div><b>Explore: </b>The Explore tab contains various things for performing exploratory work on your data to help understand distribution. </div><div>&nbsp;</div><div><b>Test: </b>The Test tab allows you to perform various statistical tests, from the T-test and F-test to others I've never heard of!</div><div>&nbsp;</div><div><b>Transform: </b>The Transform tab lets you clean up or modify your data set, using techniques such as ranking or rescaling.&nbsp;</div><div>&nbsp;</div><div><b>Cluster: </b>The Cluster tab lets you do various forms of clustering from numeric K-means clustering, to heirarchical and biclustering. </div><div>&nbsp;</div><div><b>Associate: </b>The Associate tab lets you do association rule data mining, which would be great for doing market basket analysis for retail data mining.&nbsp;</div><div>&nbsp;</div><div><b>Model: </b>The Model tab lets you create decision tree models, random forests, neural nets and other sophisticated data models.&nbsp;</div><div>&nbsp;</div><div><b>Evaluate: </b>The Evaluate tab is crucial because it helps you determine how well your model has worked. It provides an error matrix showing true outcomes versus the predicted outcomes.&nbsp;</div><div>&nbsp;</div><div><b>Log: </b>Lastly, the Log tab records all the actions run by your R code in Rattle, which helps you monitor performance, progress and errors.&nbsp;</div><div><h2>4. Load a data set</h2></div><div>In order to do your exploratory data analysis (EDA) you're going to need some data. I used one of the data sets provided by the Guardian, who have done some cracking work for data journalism by crunching public sets of data and reporting their findings. I went for the June 2012 list of <a target="_blank" href="https://docs.google.com/spreadsheet/ccc?key=0AonYZs4MzlZbdG03eE5OdHpTU0pHeEZ1MFBMS0h1MVE#gid=71">unemployment claimants by constituency</a>. It opens in Google Docs, so you'll need to export it from there as a CSV file for import into Rattle.&nbsp;</div><div>&nbsp;</div><div>In Rattle, click the Data tab, select the CSV file you download and then click the Execute button. You'll probably be prompted to install the libraries for PMML (Predictive Model Markup Language), so you'll need to install these in order to continue. </div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="248" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007e2b8c3f9b.jpg" onmouseover="undefined" onmouseout="undefined"></div><div>&nbsp;</div><div>After the PMML package has been installed in R, you should see your data set load in the bottom pane of the Rattle GUI. Now that the data set is loaded into Rattle, you'll be able to start crunching it to see what you can find.&nbsp;</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="339" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007e33cd781b.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;&nbsp;</div><div><h2>5. Exploring your data set</h2></div><div>The Explore tab of Rattle contains various tools that you can use to explore your data set. Click the Tab and select your chosen options and then hit the Execute button. If there are dependencies required you might need to install them as you go along.&nbsp;</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="233" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007e424a41ad.jpg" onmouseover="undefined" onmouseout="undefined"></div><div>&nbsp;</div><div>After any required packages have been installed and loaded, you should see that Rattle has analysed your data against a range of statistical tools and will provide a summary of its findings in the bottom pane.&nbsp;</div><div>&nbsp;</div><div>If you select the Summary radio button and then click Execute you'll get back a full summary of the data covering the data values, maximum, minimum, medians and so on. If you want additional information, click the checkboxes and then hit Execute again to get an updated textual summary. &nbsp;</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="337" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007ed13c2a7b.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div>To get a visual representation of trends in your data you can use the Distributions, Correlation or Principal Components radio buttons. Without properly defining the specific data you want to plot, you'll get a mishmash of data which looks extremely impressive, but is hard to comprehend.</div><div>&nbsp;</div><div>Presumably, the idea is to utilise this to spot patterns in your data and then refine your analysis to only those key bits of data so you can drill-down and examine the specifics in greater detail.</div><div>&nbsp;</div><div>&nbsp;<img alt="" border="" hspace="" vspace="" width="426" height="425" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5007ee3a6c63a.jpg" onmouseover="undefined" onmouseout="undefined"></div><div>There are a gazillion features, options and settings available for you to analyse and explore your data, and it's all at the click of a button, with no need to manually enter anything in the command line. Obviously this only scratches the surface of what you can do, but hopefully it's enough to get you started.&nbsp;</div>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=240&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_240]]></link>
			</item>
			<item>
				<title><![CDATA[Tracking ecommerce product additions in Google Analytics]]></title>
				<description><![CDATA[Here's a simple technique for monitoring the addition of new products to your ecommerce platform using Google Analytics. 

<p>There are two key things you need to get right in ecommerce. You need to list the right products and you need to offer them at a competitive price. The more products you add, the more revenue you'll make in the future.&nbsp;</p><p>As a result of this simple rule, most ecommerce teams have targets for their content producers and editors to hit which define how many new product ranges they need to add. </p><p>While it's possible to track this in a spreadsheet, it's laborious given that it's something that can be easily automated using Google Analytics.&nbsp;</p><h2>Step 1: Capture when products are added</h2><p>To allow you to monitor which products have been added or edited, and by which editor, you can use event tracking. To do this you'll need to place the Google Analytics tracking code onto the header of your ecommerce platform's back-end templates, allowing you to track activity by staff members on this private part of your site.&nbsp;</p><p>You might need to add a little server-side logic, but the overall aim is to capture the name of the staff member (usually available in their session data) and the name of the product they've added.</p><p> You can then simply write this data into the Google Analytics tracking code using your server-side language and add the variables you've captured.&nbsp;</p><p>&nbsp;</p><p><code>['_trackEvent', 'Content: Product added', '$product', '$author']</code></p><p>Which will write code like this to your tracking tag when the page is created, storing the data in the event tracking section of the Google Analytics UI.&nbsp;</p><p>&nbsp;</p><p><code>['_trackEvent', 'Content: Product added', 'MacBook Pro Retina', 'Matt Clarke']</code></p><p>If you want to track when products are edited or when blog posts are added you can use the same kind of technique. </p><p>Now, you'll be able to see the total number of products that have been added over a particular time period to see how well the team are meeting their product additions targets.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="251" align="" title="undefined" mce_src="/custom/images/medium/50177eb58147f.jpg" src="/custom/images/medium/50177eb58147f.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>&nbsp;</p><h2>Step 2: Creating a custom dashboard</h2><p>To help you monitor all of the product additions and edits made, and to see how well individual members of the content team are performing to their targets, you can create a dashboard to help you monitor all these metrics in one place.&nbsp;</p><p>I recorded total product additions by editor as a table, individual metrics for total products added, total products edited, total ranges added, total ranges edited, tables showing the individual products added and edited, and pie charts showing the performance of team members.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="361" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5017800d18c9b.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>You can get a copy of the dashboard <a href="https://www.google.com/analytics/web/permalink?type=dashboard&amp;uid=kg8F8xe3S2yYn3-wPxC7bg">here</a>. The event category and action values in this match those I configured in my tracking code, so you will need to change these depending on the values you enter. Every week, you can get Google Analytics to send this report to you so you can check on progress.&nbsp;</p><p>&nbsp;</p><h2>Step 3: Custom reports</h2><p>Since the dashboard only displays a summary, I also set up some custom reports to provide additional data. I made one to record all of the products added, one to record all of the products edited, and then individual reports for each member of the content team.&nbsp;</p><p>This allows me to see not only the performance of the entire team, but also how many products individual team members added and what they were.&nbsp;Here's an <a href="https://www.google.com/analytics/web/permalink?type=custom_report&amp;uid=SsI5gWQ-RU-GNSn9gtTwNQ">example report</a> showing all product additions. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="275" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/501782608e763.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>The next step is in measuring the value provided by the new products that have been added, but I'll explain that in another post. &nbsp;</p><p>&nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=236&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_236]]></link>
			</item>
			<item>
				<title><![CDATA[Undocumented features in the Google Analytics tracking code]]></title>
				<description><![CDATA[Yesterday I stumbled across some documentation for an as-yet unreleased feature in the Google Analytics JavaScript tracking code for _setPageGroup, but this is not the only unreleased feature present in the code...

<p>As you would expect, Google tests new additions to the Google Analytics tracking code and to the user interface for a long time before they're released to the general public. Google Analytics Certified Partners get to play with them and report back to Google on what they see. </p><p>While the general public using GA don't get to see the beta features of the UI, the Google Analytics Tracking Code functions are there for anyone to see if you grab a copy of the ga.js file and decompress it to make the JavaScript readable.&nbsp;</p><p>I took a quick look at the current GATC to see what functions were in there and which ones were potential new features Google is currently testing for future releases of Google Analytics. These are a few of the things I spotted. I'm sure there are quite a few I've missed!&nbsp;</p>

<h3>_setPageGroup</h3>
<p>The <code>_setPageGroup</code> function appears to work a little like a page-level custom variable and is designed to allow users to group pages according to things like their function or their author. </p>

<p>According to the guide in Google's help pages which explains how to <a mce_href="http://support.google.com/analytics/bin/answer.py?hl=en&amp;answer=2372127" target="_blank" href="http://support.google.com/analytics/bin/answer.py?hl=en&amp;answer=2372127">Interpret Page Groups</a>, you can categorise pages by type and authorship using a hierarchical system with new functionality due to appear in the reports later on.</p>

<p>This looks like a really nice new feature. Presumably, given the fact that it's currently in the help system and that there's a <a target="_blank" href="http://support.google.com/analytics/bin/answer.py?hl=en&amp;answer=2372136">Page Groups Best Practices Guide</a> visible, it's probably also due to be released fairly soon.</p>

<p>It's been possible to achieve similar results using event tracking and page-level custom variables, as I've been doing on this blog for a couple of years, using code like this: <code>_gaq.push(['_setCustomVar',5,'Author','Matt_Clarke',3]);</code>, however, the new <code>_setPageGroup</code> method appears to add a lot more functionality to the UI through the improved separation of data.</p>

<p>As a quick test, I tried implementing the <code>_setPageGroup</code> code on this site and it appears to work. There's currently no official documentation on how to use the function, but using a similar format to custom variables, using slots, seems to work.</p>

<p>So, I am guessing that creating an authorship page group might work a bit like this: <code>_gaq.push(['_setPageGroup', 3, 'Author: Matt_Clarke']);</code>. The GATC definitely picks it up. The data gets sent to Google using the new <code>utmpg</code> GIF request parameter. Presumably there will also be a few other attributes you can pass to it, though.</p><p>Following a Twitter discussion on this yesterday, Yehoshua Coren (@AnalyticsNinja) reckons it won't add an extra page hit either, as it's treated in the same way as a page-level custom variable. Indeed, the Google Analytics Debugger for Chrome currently reports it as this, emphasising the underlying similarities between the two features.&nbsp;</p><p><b>Update (July 30, 2012): </b>Looks like Content Grouping is definitely on the way. Here's a screenshot from the recently announced Remarketing Lists feature which shows Content Grouping on the Admin control panel. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="147" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/5017aeea4eb86.jpg" onmouseover="undefined" onmouseout="undefined"></p>

<h3>_setAutoTrackOutbound</h3>
<p>The <code>_setAutoTrackOutbound</code>&nbsp;function has been in the Google Analytics tracking code for ages. I can remember reading about it at least a few years ago when Phil Pearce (@philpearce) <a target="_blank" href="http://productforums.google.com/forum/#!topic/analytics/Xg43gbKqMC4">discussed it here</a>&nbsp;when we were all still using the old synchronous GATC.&nbsp;</p>

<p>The idea is that by adding this function to your JavaScript tracking code, Google Analytics will then record any clicks on outgoing links. At the moment, this is possible but you do have to either manually attach events or virtual pageviews to each link, or apply it to all external links using the DOM or jQuery. &nbsp;</p><p>It's possible to send data, but as far as I know, there's no way to view the outbound links from&nbsp;<span style="font-family: monospace; ">_setAutoTrackOutbound</span>&nbsp;in Google Analytics at the moment. Is the also undocumented&nbsp;<span style="font-family: monospace; ">_setHrefExamineLimit&nbsp;</span>related?</p>

<h3>_clearTrans</h3><p>Could&nbsp;<span style="font-family: monospace; ">_clearTrans</span>&nbsp;be a new function to remove ecommerce transactions from your data? This can be an issue when you need to process refunds and want the revenue data removed, or when you've been subject to black hat techniques which have injected data into your account.&nbsp;</p><p>There is, of course, a workaround for this at the moment, but no official function yet. So perhaps this is it. &nbsp;</p><p>Whatever it does, there's nothing currently written about&nbsp;<code>_clearTrans</code> and using it in a simple manner as <code>_gaq.push(['_clearTrans','1234']);</code> appears to add nothing to the GIF request, so presumably it either requires additional parameters or depends on the presence of an additional function.</p>

<h3>_setMaxCustomVariables</h3><p>A year or so ago, the <code>_setMaxCustomVariables</code> function used to work, as I've explained before <a href="http://techpad.co.uk/content.php?sid=165">in this post</a>. By passing an integer, such as 10, to the function in your GATC, you used to be able to get more than the usual five custom variables.</p>

<p>However, just before Google Analytics Premium came out (which provided 50 custom variables instead of five) it stopped working. The data would still be sent, but clicking on them resulted in an error page in the UI. I can only assume that this function, which was never really announced by Google, will now be deprecated.</p><p><b>Caveat</b></p><p><b></b>Obviously, this is unreleased, undocumented, dangerous stuff, so don't use it in a production environment!&nbsp;&nbsp;</p>





]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=234&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_234]]></link>
			</item>
			<item>
				<title><![CDATA[Connecting to MySQL on Amazon EC2 over a SSH tunnel]]></title>
				<description><![CDATA[If you need to administer a MySQL server on an Amazon EC2 instance and don't want to use the command line, or install phpMyAdmin, you can do it graphically using MySQL Workbench and SSH.

<p>Many people view phpMyAdmin as something of a security risk. It's quite common for servers to be scanned looking for the presence of this web application, so if you forget to update it, there's a risk that attackers might breach your server, so it's safer not to install it at all.&nbsp;</p><p>While I'm comfortable using the command line for most stuff in MySQL, there are times when it's faster and more productive to use a GUI, and the new MySQL Workbench suite makes this quite easy. It's much like the old MySQL Administrator and MySQL Query Browser it replaces in that it can connect to MySQL over a SSH tunnel, and if anything it's now easier than ever.</p><p>While this example shows it on OS X, MySQL Workbench is cross platform and the same procedures should apply to any operating system. </p>

<h3>Creating your tunnel</h3>
<p>Open MySQL Workbench and click "New Connection". Enter a connection name, such as "Amazon EC2" and select "Standard TCP/IP over SSH" as the connection method.</p>

<p>In the SSH Hostname field you need to enter the Elastic IP for your EC2 instance. Unless you've configured SSH to use a port other than the default 22, leave the port :22 part as it is. For the username field you'll need to enter your SSH username. On Ubuntu Amazon EC2 instances the default username is "ubuntu", so enter that. </p>

<p>Amazon EC2 doesn't provide an SSH username and password, but instead provides a PEM certificate or key which you can store on your local machine to provide access. Click the "..." button on the SSH Key section to select your PEM key. </p>

<p>Again, if you've not done anything fancy with your MySQL installation, you can leave the default port as 3306 and use whatever user you've added, or connect with the root account if you're performing admin tasks. Finally, enter your default schema name and hit OK and you should have a remote connection to your MySQL database tunneled via SSH.</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=233&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_233]]></link>
			</item>
			<item>
				<title><![CDATA[Mounting Amazon EC2 instances on OS X with SSHFS]]></title>
				<description><![CDATA[After 12 years as a Linux user I have recently switched to Mac OS X on my laptop and some things are a touch trickier, including setting up access to Amazon EC2 instances in the cloud. 

<p>On Linux it's really easy to mount your Amazon EC2 instances on your local development machine so you can drag, drop, edit and delete files. However, since Amazon EC2 uses PEM certificates rather than passwords and usernames, setting it up on a Mac is a little more difficult.&nbsp;</p><p>A few of the guides I checked suggested using MacFuse and Macfusion, however, neither of these appear to work on OS X Lion. MacFuse is now unsupported and Macfusion seemed really buggy, so I had to find an alternative method. Thankfully, it was pretty easy once I figured out what package was needed.&nbsp;</p>

<h2>Step 1: Set up SSH</h2>
<p>In my fresh install of Mac OS X Lion I didn't have a hidden .ssh directory inside my home directory so the first thing I needed to do was open a terminal and create one: <code>mkdir ~/.ssh</code></p>

<p>I then opened the Finder on that directory using <code>open ~/.ssh</code> and dragged the PEM key into the directory. It's vital now to change the permissions of the key, because if it's insecure SSH will (cleverly) not let you use it. You can do this by entering <code>chmod 600 ~/.ssh/YourKeyName.pem</code></p>

<p>Now that the PEM key is in place, you ought to test that it works by entering <code>ssh -i ~/.ssh/YourKeyName.pem ubuntu@1.2.3.4</code>, where 1.2.3.4 is the IP of your EC2 instance that you've added using an Elastic IP.</p>

<p>Once you're sure that the key works as intended, you can store it in SSH so it can run without the need to manually use the <code>-i</code> flag or enter the path to the key itself. You can add the key to SSH by typing: <code>ssh-add -K ~/.ssh/YourKeyName.pem</code></p>

<p>Now it should be possible to access your Amazon EC2 instance from the command line simply by typing <code>ubuntu@1.2.3.4</code> and SSH will simply use the certificate you stored to gain access.</p>


<h2>Step 2: Mounting the Amazon EC2 filesystem locally</h2>
<p>To mount the Amazon EC2 filesystem on your Mac you'll need to download and install the <a mce_href="http://osxfuse.github.com" target="_blank" href="http://osxfuse.github.com">SSHFS package</a> from the OXSFuse project. It's free and open source and installs as a panel in System Preferences. </p>

<p>Now you need to create a local mount point for the Amazon EC2 instance which you can do by entering <code>mkdir ~/AmazonEC2</code></p>

<p>In its simplest form, you can mount the EC2 instance by entering <code>sshfs ubuntu@1.2.3.4:/var/www ~/AmazonEC2</code> - where <code>ubuntu</code> is your EC2 username and <code>/var/www/</code> is the default directory you want to show on the mount point.</p>

<p>There are, of course, a ton of optional parameters, and you can probably configure OS X to mount this automatically at boot time if you want, but this is sufficient for basic access to an EC2 instance in a graphical environment. </p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=232&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_232]]></link>
			</item>
			<item>
				<title><![CDATA[Email open rate tracking in Google Analytics]]></title>
				<description><![CDATA[Here's how you can track the open-rate of emails using Google Analytics. 

<p>Email open rate - the number of people who actually open the emails you send - is a key performance indicator in email marketing. If you can increase the number of people who open your emails you'll almost certainly generate more results from them. (Though personally I prefer to <a href="http://techpad.co.uk/content.php?sid=126">measure goals</a> instead.)&nbsp;</p><p>Google Analytics provides some really useful campaign tracking parameters for monitoring the performance of email marketing campaigns, so you can measure how many clicks you get from them, how many visits they drive and which parts of your email are most appealing.</p><p>However, there's no recommended method for using Google Analytics to monitor your email open rate and it's not really what GA was intended for.&nbsp;</p><p>Most people do it using their email service provider (ESP), which is definitely what I'd recommend. However, quite a few people seem to want to do something similar in GA, so I thought I'd explain briefly how it can be done.&nbsp;</p><h3>Tracking email open rate in Google Analytics</h3><p>Although it's possible to send HTML emails, you can't simply stick the standard JavaScript tracking code in your email and expect it to be tracked. </p><p>Email clients (including web mail systems like Windows Live mail and Gmail) strip out JavaScript for security reasons, so it wouldn't get executed and you'd receive no data back. Instead, what you need to do is use old-school pixel tracking.&nbsp;</p><p>The standard client-side Google Analytics tracking code takes data gleaned from your page using JavaScript and cookies and adds it to a GET request string appended to an invisible single pixel transparent GIF image called __utm.gif. </p><p>Each time you do something on a site with Google Analytics installed, the __utm.gif has HTTP GET parameter data appended to the end which is picked up by the Google Analytics server, parsed and then added to your GA account.&nbsp;</p><p>You can take a look at the GIF request that gets sent to Google Analytics by using a tool like Firebug on Mozilla Firefox or the Google Analytics Debugger extension for Google Chrome. Here's an of some of the data which gets appended to the GIF request below.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="164" align="" title="undefined" mce_src="http://techpad.co.uk/custom/images/medium/4ff96e8d4b7a9.jpg" src="http://techpad.co.uk/custom/images/medium/4ff96e8d4b7a9.jpg" onmouseover="undefined" onmouseout="undefined"></p><h3>Using mobile Google Analytics tracking</h3><p>It used to be the case that mobile phone browsers didn't always execute JavaScript, so to overcome this issue, Google helpfully provided an alternative mobile tracking code. </p><p>This didn't rely on JavaScript and simply used a GIF request instead. Instead of the GET parameters being populated by JavaScript, it utilises a server-side language, such as PHP, to populate the values and create the GET parameters required by GA.&nbsp;</p><p>When a mobile device views a page containing the GIF, the server grabs the data it needs from the device and server, populates the GET parameters and sends the data to Google Analytics.&nbsp;</p><p>Since email clients are a bit like old mobiles in that they don't execute JavaScript, you can use the same kind of technique to send data when an email is viewed.&nbsp;</p><p>While you might be able to tweak the standard __utm.gif, I think the easiest way to utilise this technique is to use the mobile tracking code, which works using PHP.&nbsp;</p><h3>Setting up the mobile tracking</h3><p>To get started, the first thing you'll need to do is obtain a copy of the Google Analytics tracking code for mobile devices. </p><p>To find this, click Admin &gt; Tracking code &gt; Advanced &gt; PHP and you should find the PHP code required, and the MO-123456-1 web property ID required in the textarea below.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="368" align="" title="undefined" mce_src="http://techpad.co.uk/custom/images/medium/4ffbcca76dc0e.jpg" src="http://techpad.co.uk/custom/images/medium/4ffbcca76dc0e.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>The other vital thing to obtain is a copy of the ga.php Google Analytics mobile code, which you can <a mce_href="https://ssl.gstatic.com/analytics/20120619/mobile/ga.php" href="https://ssl.gstatic.com/analytics/20120619/mobile/ga.php">download from here</a> and install on your web server.&nbsp;</p><p>Save the example code to a PHP file and load it in your browser, making sure you've pointed to the ga.php Google Analytics file you installed in the previous step. </p><p>After loading this, you should be able to see the GIF/GET request in the Google Analytics Debugger extension for Chrome and your data should appear in GA a few minutes later.&nbsp;</p><h3>Creating campaign tracking</h3><p>What we have now is a script (ga.php) that can be loaded in a HTML image tag by a web browser and which passes a string of GET parameters back to the Google Analytics servers, and serves up a transparent GIF for the browser.&nbsp;</p><p>However, since we can't run PHP inside an email, we need to manually populate the GET parameters. As well as the standard ones used by the mobile tracking, you can also utilise Google Analytics' other tracking methodology, including the campaign tracking parameters.</p><p>Don't forget that anything you include in your URL needs to be URL encoded so it doesn't break the URL. This means converting &amp; to &amp; and spaces to %20, among other things. &nbsp;</p><p>Here's a working example which tracks a newsletter campaign, to which I've added some spacing and line breaks to improve readability. Simply copy this and replace the values with your own.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="122" align="" title="undefined" mce_src="http://techpad.co.uk/custom/images/medium/4ffbd147a05dd.jpg" src="http://techpad.co.uk/custom/images/medium/4ffbd147a05dd.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>You will need to replace the utmac value with your own mobile web property ID; the utmn value should ideally be a random number assigned to each email; the utmr is the referral field which you can leave empty; the utmp is the address of the page, to which you can pass any appropriate value; while the utmp parameter contains your URL encoded campaign parameters.&nbsp;</p><p>For the campaign tracking, I used the standard utm_source (newsletter), utm_medium (email), utm_campaign (July) and utm_term (Offer1).</p><p>Now, all you need to do is add the HTML code for this GIF request to your email inside a standard HTML <img> element, ensuring that you're pointing to the ga.php you hosted earlier. </p><p>Then stick it at the bottom of your email and send a test mailing to yourself. If you open the email, it should send a request to your pixel tracking code and pass the data to your GA account, where it should appear shortly afterwards.</p><h3>Don't forget...</h3><p>While it works, in theory, the results you get in practice may be different to those you get from your ESP's open-rate tracking.</p><p>This reports gross-opens and might require the utmn value to be populated with a unique numeric identifier in order to pick up unique opens. </p><p>It might not be hugely reliable without this, because if the same user repeatedly opens an email it will skew the gross opens, making you think the email has been opened by more people than it really was. </p><p>As a result, I'd recommend testing it thoroughly before you rely on the data.&nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=231&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_231]]></link>
			</item>
			<item>
				<title><![CDATA[How to ditch your email preference centre with RFM]]></title>
				<description><![CDATA[I've always hated email preferences centres, so I ditched ours by doing some data crunching with RFM and latency analysis, and the results have been brilliant. 

<p>If you run an ecommerce site which sells products across multiple categories, it can be fairly common for customers to only shop in one or two related to their interests or requirements. </p><p>This makes email marketing a challenge, because pretty much the only way you can target them with relevant emails is to ask them to fill in a preference centre style form, and people hate filling them in.&nbsp;</p><p>Relevant emails are much more likely to be opened and generate more purchases and fewer unsubscribes, so it's worth taking the effort to improve in this area. </p><p>I built a tool to do just this, and ditched the preferences centre by extracting the data I needed using RFM. Here's a quick run down of how it works.&nbsp;</p><p><b>1. Create a segment</b></p><p><img alt="" border="" hspace="" vspace="" width="426" height="309" align="" title="undefined" mce_src="/custom/images/medium/4fe2c213c23bb.jpg" src="/custom/images/medium/4fe2c213c23bb.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined">&nbsp;</p><p>I created a segment for each subcategory within the taxonomy of the site. These typically use some default RFM settings I came up with based on rules related to our business and the type and value of products sold, however, I also added the ability to over-ride this and adjust the RFM settings on a per-subcategory basis.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="742" align="" title="undefined" mce_src="/custom/images/medium/4fe2c2d0760f9.jpg" src="/custom/images/medium/4fe2c2d0760f9.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined"></p><p><b>2. Managing segments</b></p><p>Sometimes it's useful to know how many customers you've got in each segment, and what the average RFM score is. You might also want to adjust the RFM settings for the segment, so I added a tool to handle this. You need to delete the data from the segment if you're changing the settings, since the RFM analysis will obviously be utilising different data. </p><p><img alt="" border="" hspace="" vspace="" width="426" height="274" align="" title="undefined" mce_src="/custom/images/medium/4fe2c3b928ea2.jpg" src="/custom/images/medium/4fe2c3b928ea2.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined"></p><p><b>3. Creating groups</b></p><p>In order to create groups of customers to target, I created a tool allowing the user to select which of the segments they wanted to include. If you want to target only owners of mountain bikes, you'd select all of the subcategories related to this and create a name for the group to identify the cluster.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="277" align="" title="undefined" mce_src="/custom/images/medium/4fe2c4c8e94b5.jpg" src="/custom/images/medium/4fe2c4c8e94b5.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined"></p><p>You'll also need a tool for managing the groups you've created. In this I included the ability to edit and delete them, and listed the number of customers in each one, the number contactable (due to opt-in settings) and the number for which the group is their top scoring group.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="320" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fe2c6dcbb656.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined">&nbsp;</p><p><b>4. Scoring customers</b></p><p>The complicated part is the scoring of the customers. To do this, I grabbed a copy of the site's historical basket data and the customer data and stored it on the server that does the number crunching. </p><p>The basic concept is that you create some algorithms which loop over each customer's purchases and score them in every segment using the settings you defined when each segment was created. </p><p>Obviously, this is really intensive and the data crunching can take several days for a large data set. However, you do end up with some really useful data.&nbsp;</p><p>At the same time, I also do some other ecommerce data crunching, and look at things like purchase latency. For this part, I'd highly recommend getting yourself a copy of <a href="http://www.jimnovo.com/" target="_blank" rel="nofollow">Jim Novo</a>'s excellent book Drilling Down, which covers all aspects of mining customer data using such techniques.&nbsp;</p><p><b>5. Create your lists</b></p><p>The whole point of this system is that you use it to cluster customers so they're contacted with offers most appropriate to their current interests. If you spend lots of money on skiing, but go surfing in the summer, you won't want to receive skiing-related emails when it's hot outside. </p><p>When exporting lists, the tool clusters customers so they're placed in their top-scoring RFM group and don't get placed in multiple lists. When you're creating your custom emails, you simply select the lists you want to mail to, and the tool exports the email addresses of the customers included.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="348" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fe2c86c2bd7a.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined"></p><p>I also added an RFM-powered tool to the exporter which allows you to drill-down a little further, by selecting only customers who have shopped within a certain time period, purchased a certain number of times, or spent over a specified amount. </p><p>This means you can create a highly targeted email allowing you to contact only repeat customers who have, for example, spent over £100 on shoes over the past 30 days. The next step is simply to use the exported list data and create the email targeted at the cluster.&nbsp;</p><p><b>6. Analysing the customer data</b></p><p>The neat thing about having all this customer data is that you can mine it to extract other useful things, such as details on purchase latency. This can be useful for email marketing, because it means you can identify customers who are lapsing and target them specifically based on what you know about the typical behaviour of the individual and other customers who shop in a given segment. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="" height="" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fe2c9f781c77.jpg" onmouseover="return true;undefined" onmouseout="return true;undefined"></p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=230&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_230]]></link>
			</item>
			<item>
				<title><![CDATA[If only Google Analytics were connected to Google Merchant Center...]]></title>
				<description><![CDATA[Given that pretty much every e-commerce retailer uses both Google Analytics and Google Merchant Center, it's a little odd that Google has joined the data from the two of these together. 

<p>The new version 5 release of Google Analytics brought tighter integration with the Google Webmaster Tools data, putting it inside GA's new Search Engine Optimisation section.</p><p> But oddly, it hasn't yet done the same with the vast amounts of data it holds on ecommerce retailers' product inventories through the <a mce_href="http://techpad.co.uk/content.php?sid=219" href="http://techpad.co.uk/content.php?sid=219">Google Merchant Center feeds</a>.&nbsp;</p><p>Google Merchant Center feeds, if you're not familiar with them, are XML files containing vast quantities of information on a retailer's product inventory.&nbsp;</p><h3>What's the point?&nbsp;</h3><p>The existing Google Merchant Center tools are pretty limited, but tying the two together could help retailers improve the return they get from their feed.&nbsp;</p><p>For Google, it would also make sense for them from a commercial point of view, because they're controversially going to start charging for inclusion on Google Products (the new name for Google Shopping or Froogle). </p><p>Much of their revenue comes from Adwords, which GA covers well, so the same strategy ought to apply equally to monitoring and optimising Google Merchant Center feeds.&nbsp;</p><p>However, on a practical level for practitioner analysts and ecommerce managers, integrating the Google Merchant Center feed data with Google Analytics would have several benefits, beside the obvious one of allowing better feed optimisation.&nbsp;</p><p>It would also greatly improve the rather limited ecommerce functionality in GA at present, which in my opinion is perhaps its weakest area from a practical perspective.&nbsp;</p><p><b>1. Product conversion rates</b></p><p>If you're an ecommerce manager one of the key things you'll want to measure is the conversion rate of individual products, but this is not something Google Analytics really provides, which I find rather odd.</p><p>If you know the conversion rate of each product you can use it to identify those which aren't performing well, indicating potential problems with content, imagery, merchandising or price, which means you're better able to fix them.&nbsp;</p><p>Both the URL of the product and its SKU are used appear in both the Google Analytics data and in the Google Merchant Center feed data, so either can be used as a primary key to join the two together.&nbsp;</p><p>I've previously built a proof-of-concept application using the Google Analytics Core Reporting API and the Google Content API for Shopping which does just this, allowing me to see accurate product conversion rates for any SKU or page, without the need to do anything in Excel. </p><p>I can even pull in the product image and description and other data to see if there are issues with that. It makes the whole process of checking product content much easier.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="292" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fdecf19712d3.jpg">&nbsp;&nbsp;</p><p><b>2. Brand analysis</b></p><p>As an ecommerce manager, one of the other things you'll want to look at is how well different brands are performing across your site. At the moment you can do this using advanced segments, or the excellent new dashboard tools, but it's still very much a manual process and it's lacking in some information.&nbsp;</p><p>However, the Google Merchant Center feed data contains a brand field, so if it were incorporated into GA, it would be able to show you the performance of every brand stocked without the need for you to manually create an advanced segment and multiple reports to examine each one.&nbsp;</p><p>You'd then be able to see what proportion of revenue or visits were to different brands, see how each was performing and examine the customer segments associated with each one. It could be really useful for retailers. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="195" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fdece355ab7e.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>3. Feed quality analysis</b></p><p>The bit that will probably appeal most to Google from a commercial angle would be the incorporation of feed quality data. At the moment, you can get this (at a very basic level) in the Google Merchant Center application, but it's not brilliant.&nbsp;</p><p>It would be nice to be able to see, for example, which of your products were missing key parts of information such as barcodes, and identify what difference that had to conversion rates. &nbsp;</p><p>From past work on Google Merchant Center feed optimisation, I'm fairly certain that feed errors are used as a ranking factor in Google's Product search, so showing these in GA would also help retailers fix problems and spot what was happening more easily. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="298" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4ea00196dd67d.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>4. Cost data</b></p><p>The other thing I've felt Google Analytics and the Google Merchant Center feeds have long required is cost data. At the moment, there's no way to see how profitable your ecommerce activity has been, or whether your Adwords campaigns broke even, turned profit or ran at a loss, unless you export the data and add your own external cost data.&nbsp;</p><p>However, since the Google Merchant Center feeds are made available only to Google, it would be really simple to add an additional field containing the cost price, which would then greatly extend the functionality and usefulness of GA. </p><p>I appreciate that many people say GA isn't a financial tool, but nonetheless, having this data available within GA would be really, really handy, and I think pretty easy to introduce.&nbsp;</p><p>I'm already doing something similar using the ecommerce tracking, but using server-side code to push the cost/margin data into GA rather than using the client-side code, which obviously shows confidential data in the page source.</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=228&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_228]]></link>
			</item>
			<item>
				<title><![CDATA[Getting started with NoSQL: MongoDB in PHP]]></title>
				<description><![CDATA[A quick guide to getting started with the high performance MongoDB NoSQL database using PHP on Linux. 

<p>MongoDB is a high performance open source NoSQL document-oriented database which stores data in JSON-like files called BSON dynamic schemata, instead of storing data in the usual relational tables. This makes it fast and really scalable.&nbsp;</p><p>It's particularly good for handling real time data, such as lots of inserts, updates and queries, which makes it well suited to powering API services for SaaS software and it's already being used by big sites like Craigslist and Foursquare.&nbsp;</p><p>In many ways it's rather like Apache CouchDB, but it requires its own drivers (rather than using a REST API), it scales using <a target="_blank" href="http://en.wikipedia.org/wiki/Shard_(database_architecture)">sharding</a> rather than replication, and it supports more datatypes. It's one of the easiest of the "big data" technologies to get started with and it works very well with PHP.</p><p><b>1. Install MongoDB</b></p><p>To install MongoDB on a Debian-based system open a terminal and enter "sudo apt-get install mongodb" to install Mongo and its dependencies. Once it's finished installing, enter "mongo" and you should see MongoDB's command line in your shell.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="300" align="" title="undefined" mce_src="/custom/images/medium/4f816eac89eaf.jpg" src="/custom/images/medium/4f816eac89eaf.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>2. Create MongoDB's data directory</b></p><p>Oddly, MongoDB uses a default data directory called /data/db but it does not create this when you install it. To create the directory get a prompt and enter "sudo mkdir -p /data/db/" then "sudo chown `id -u` /data/db". </p><p><img alt="" border="" hspace="" vspace="" width="426" height="277" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f81729ba1176.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>3. Install the PHP drivers for MongoDB</b></p><p>To use MongoDB with PHP you need to make sure that the "mongod" server is running on your machine (just type in mongod into a shell to find out) and that you have the Pear installed.&nbsp;</p><p>You can install the Pear PHP system by entering "sudo apt-get install php5-dev php5-cli php-pear".&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="299" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f81880f027c9.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>Once you have Pear installed, you can use it to install the MongoDB drivers using PHP Extension Community Library (PECL) simply by entering&nbsp;"sudo pecl install mongo".&nbsp;</p><p>Once that's installed, you'll then need to manually modify your php.ini configuration file to include the line "extension=mongo.so" to ensure the Mongo drivers are loaded as a PHP language extension.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="299" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f818810538a0.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>On Ubuntu, you can edit php.ini by entering "sudo gedit /etc/php5/apache2/php.ini". You'll need to restart Apache to get the module to load so enter "sudo service apache2 restart" and you should be ready to go.&nbsp;</p><p><b>4. Creating or selecting a MongoDB database</b></p><p>Creating a new database is very easy in Mongo, instantiate the Mongo class with "$mongo = new Mongo();" then select the Mongo database you wish to use with "$db = $mongo-&gt;customers;".&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="226" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f818bbb90fd3.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>If a database doesn't already exist to be selected, Mongo will create one, so the above code example creates a database called customers, or if it already exists, selects it so we can use it.</p><p><b>5. Create a collection in your Mongo database</b></p><p>MongoDB doesn't use tables, but it does have an equivalent which is called a "collection". Collections are essentially collections of data files or "documents".</p><p>Extending our above script, we can select a collection called purchases from our customers database using "$collection = $db-&gt;purchases;". Again, if the collection doesn't exist, Mongo will create it.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="303" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f818d6421e0d.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>6. Inserting a record</b></p><p>To add a record to the collection you've created you use the insert() function. First you assign the data you want to add to an associative array, which I've called $object in the example below, then you add it to the collection with $collection-&gt;insert($object);</p><p><img alt="" border="" hspace="" vspace="" width="426" height="424" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f819b6d5d3a5.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>If you want to see the records you've added, you can run the find() function on your collection and assign the output to the MongoDB cursor and then loop over it to see the list of entries.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="162" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f819c7780729.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>7. Deleting a record</b></p><p>To delete all records matching a certain criteria, you need use the remove() function and pass it an array with the array parameters you want to match against.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="353" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4ff080441fb03.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>Like SQL, if you have multiple records that match the criteria MongoDB will delete all of those that match. However, if you use add the true parameter to the remove function it will only delete the first match. </p><p><b>8. Selecting records</b></p><p>To perform the MongoDB equivalent of a SQL SELECT statement you need to use the find() function. You pass an array of search parameters to find() and it returns any matching documents in the cursor. There are lots of different ways to use the find() function and there are some handy examples <a target="_blank" href="http://php.net/manual/en/mongocollection.find.php">shown here</a>.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="" height="" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4ff0851d6bb83.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>9. Updating records</b></p><p>The final basic thing you'll want to do is update a record, which rather helpfully is done via the <a target="_blank" href="http://www.php.net/manual/en/mongocollection.update.php">update() function</a>. However, the way it works was, to me, initially a bit confusing.&nbsp;</p><p>You pass two arrays to update(). The first one contains the details on the item you want to match against (in the example below I've matched records with the name 'Steve Jobs') while the second array contains the $set key and an array of the keys/values you want to update.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="398" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4ff0a0064f83a.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>You can also add additional fields to an existing document with update(), or you can do an "upsert" in which you update an existing object or create a new one if it doesn't already exist.&nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=225&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_225]]></link>
			</item>
			<item>
				<title><![CDATA[A quick guide to R and Google Analytics]]></title>
				<description><![CDATA[A beginner's guide to getting started with the R Statistical Computing programming language for Google Analytics data analysis.

<p>R is a programming language designed for statistical analysis and graphical data visualisation. It's a command line language, similar in many ways to Python, but can also be used from graphical applications, too.&nbsp;</p><p>R is becoming popular with analysts who want to do a bit more with the data they export from Google Analytics. While the learning curve is initially a bit steep, there's an R package for Google Analytics which can make working with, and visualising, API data a little less challenging.</p><p>I've recently been dabbling with R and Google Analytics and thought I'd share some pointers on how to get started with some simple projects.&nbsp;</p><h2>1. Install R and R-XML</h2><p>Besides R itself, the R for Google Analytics code also uses a couple of extra extensions for fetching the data from the webservice and for parsing the resulting XML.&nbsp;</p><p>I'm a Linux user and on Ubuntu/Debian you can install these by entering: sudo apt-get install r-base r-cran-xml libcurl4-gnutls-dev libxml2-dev</p><h2>2. Start R and install RCurl and XML</h2><p>To install the required RCurl package you need to start R by opening a terminal and typing R then entering a command to download the package from one of the&nbsp;<a target="_blank" mce_href="http://www.r-project.org/" href="http://www.r-project.org/">CRAN mirrors</a>. These are much like the CPAN mirrors used in Perl, but contain R packages rather than Perl packages.</p><p>The&nbsp;<a target="_blank" mce_href="http://code.google.com/p/r-google-analytics/" href="http://code.google.com/p/r-google-analytics/">Google Analytics R documentation</a>&nbsp;and code comments suggest using the www.omegahat.com mirror, however, this domain appears to no longer be in use, so I went for Imperial College's CRAN mirror, which is at http://cran.ma.imperial.ac.uk.</p><p>You can download RCurl from your chosen mirror by entering the following command in the R command line interface: install.packages("RCurl", repos = "http://cran.ma.imperial.ac.uk")</p><p>Once you've done that, issue the command below to install the XML libraries in R: install.packages("XML", repos = "http://www.omegahat.org/R")</p><h2>3. Install R Google Analytics</h2><p>There's a pre-built package for using R with Google Analytics, but it's not in Cran, so you'll need to download it the&nbsp;<a href="http://code.google.com/p/r-google-analytics/downloads/detail?name=RGoogleAnalytics_1.1.tar.gz">RGoogleAnalytics code libraries</a>&nbsp;from Google Code. However, as of September 2012, this had not been updated to work with the new Google Analytics Core Reporting API and doesn't support the namespaces required in R versions greater than 2.13, so either won't install or won't work.&nbsp;</p><p>The very helpful Richard Fergie (@richardfergie) has kindly pointed out that there's an <a href="https://github.com/JerryWho/rgoogleanalytics">unofficial version of RGoogleAnalytics</a> available on GitHub, which does work and should install. Thanks, Richard. &nbsp;</p><p>To install RGoogleAnalytics start R (just type R in a terminal) and then enter this command (with the location and file name replaced with where ever you've put the RGoogleAnalytics tarball): install.packages("/home/matt/Downloads/RGoogleAnalytics_1.1.tar.gz",repos=NULL,type="source")&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="266" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f5682610a881.jpg">&nbsp;</p><h2>4. Install RStudio</h2><p>Next, I'd recommend installing RStudio, a very powerful graphical client available for R, which is free and open source and available for Linux, Mac and Windows. You can<a href="http://www.rstudio.org/download/desktop">download it</a>&nbsp;from www.rstudio.org as a package for your OS.&nbsp;</p><p>Not only does it provide simple access to the command line, but it will also display any visualisations generated within the application itself, which is nice. The full&nbsp;<a href="http://www.rstudio.org/docs/">documentation for RStudio</a>&nbsp;will tell you more.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="280" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f5685dc8a6b2.jpg"></p><h2>5. Load the RGoogleAnalytics library&nbsp;</h2><p>If you wish to install any additional packages, click the Packages tab in the lower right hand corner of the RStudio GUI and RStudio will automatically install the selected package and its dependencies with a single click. This makes extending R really, really easy. In order to use one of the packages, you need to tick the checkbox so the libraries are loaded.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="345" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f5687c58f593.jpg">&nbsp;</p><p>When you load the RGoogleAnalytics library, you should see it fire up the dependencies in the console window.</p><p>&gt; library("RGoogleAnalytics")<br>Loading required package: RCurl<br>Loading required package: bitops<br>Loading required package: XML</p><h2>6. Connect to the Google Analytics Core Reporting API</h2><p>Using the source editor window at the top right of RStudio write a few lines of code to start up RGoogleAnalytics in R, pass your login credentials to the Google Analytics Core Reporting API and fetch your profile data.&nbsp;</p><p>ga &lt;- RGoogleAnalytics()<br>ga$SetCredentials("you@yourdomain.com", "qkjshdjkdsksk")<br>profiles &lt;- ga$GetProfileData()<br></p><p><img alt="" border="" hspace="" vspace="" width="426" height="114" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f57c48d9bfcb.jpg">&nbsp;</p><p>Highlight the text you've written and then click the "Run" button to execute this chunk of code - you should see some results in the Workspace window pane. &nbsp;</p><p>Click the "Profiles" option and you should get a pop-up window containing all of the profiles for your ID and all of the table IDs for your GA tables. You'll need to grab one of the table IDs to use to query GA.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="233" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f57c6957c5ef.jpg"></p><h2>7. Running basic GA queries</h2><p>Once you have an open connection to GA, you can now compose a Google Analytics API query to pass to the Core Reporting API using the QueryBuilder() function. Here's a basic example to fetch visitors and pageviews for a given date period.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="226" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f57c80730ba2.jpg">&nbsp;</p><p>When the query runs you should see it pause for a second while it queries the Google Analytics servers and then display the results in the console window on the bottom left had corner of RStudio.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="209" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f57c8e778042.jpg"></p><p>While handy, at the moment, this isn't anything you couldn't achieve either via the Data Feed Query Explorer or via the Core Reporting API in any other language that takes your fancy.&nbsp;</p><h2>8. Plotting data</h2><p>R has tons of features for quickly plotting data and applying statistical calculations to data sets. Basic plots are achieved using the plot() function while trend lines can be added using lines().</p><p><img alt="" border="" hspace="" vspace="" width="426" height="248" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4fba6252a43f6.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>You can do this on your GA data with:</p><p><code>

# Set up RGoogleAnalytics
</code></p><p><code>ga &lt;- RGoogleAnalytics()
</code></p><p><code>ga$SetCredentials("YOURUSERNAMEHERE", "YOURPASSWORDHERE")
</code></p><p><code>profile.data &lt;- ga$GetProfileData()
</code></p><p><code>my.table.id &lt;- "ga:YOURTABLEIDHERE"</code></p><p>&nbsp;</p><p><code>
# Build your GA query
</code></p><p><code>query &lt;- QueryBuilder()
</code></p><p><code>query$Init(</code></p><p><code>start.date = "2011-01-01",
</code></p><p><code>           end.date   = "2011-05-20",
</code></p><p><code>           dimensions = "ga:week",
</code></p><p><code>           metrics    = "ga:itemRevenue",
</code></p><p><code>           sort       = "ga:week",
</code></p><p><code>           table.id   = my.table.id)
</code></p><p>&nbsp;</p><p><code># Run the query
</code></p><p><code>ga.data &lt;- ga$GetReportData(query)
</code></p><p><code>head(ga.data)
</code></p><p>&nbsp;</p><p><code># Create chart
</code></p><p><code>require(stats)
</code></p><p><code>plot(ga.data$data, type="o", col="blue")&nbsp;</code></p><p><br></p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=220&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_220]]></link>
			</item>
			<item>
				<title><![CDATA[How to improve your Google Merchant Center feed quality]]></title>
				<description><![CDATA[Keeping your Google Merchant Center feeds low on errors and warnings will keep the traffic and revenue coming in. Here are some pointers on how to improve feed quality. 

<p>Google Merchant Centre (formerly Google Base) feeds are XML or text files which contain data on the products sold in your e-commerce platform and they power both Google Shopping and the product extensions in Google Adwords. </p><p>

Google sets strict criteria on data quality and error limits and if you don't monitor these you risk having your feed penalised and some or all of your products de-listed.</p><p>

In September 2011, Google started gradually enforcing new <a target="_blank" mce_href="http://merchant-center-announcements.blogspot.com/2011/09/we-have-gradually-begun-enforcing.html" href="http://merchant-center-announcements.blogspot.com/2011/09/we-have-gradually-begun-enforcing.html">feed specification requirements </a>and if you didn't update your feed then it's possible you may have experienced a traffic and revenue drop from this source.</p><p> 

Among the new additions were the requirement to provide data on product availability, the Google Product Category and images. </p><p>If you sell clothes and shoes there are <a target="_blank" mce_href="http://merchant-center-announcements.blogspot.com/2011/07/weve-made-changes-to-google-product.html" href="http://merchant-center-announcements.blogspot.com/2011/07/weve-made-changes-to-google-product.html">additional things</a> you need to provide too.</p><h2>

Step 1: Examine the Dashboard</h2><p>Login to the Google Merchant Centre and open the <a target="_blank" mce_href="http://www.google.co.uk/merchants/merchantdashboard" href="http://www.google.co.uk/merchants/merchantdashboard">Dashboard</a> for the site you want to examine.

</p><p>The Dashboard shows some charts outlining the number of products that are active, awaiting review, disapproved or expiring for the Product Search and Product Ads; the number of search clicks; a summary of data quality and the total number of items inserted. 

</p><p><img mce_src="/custom/images/medium/4f5614b429bf4.jpg" height="265" width="426" src="/custom/images/medium/4f5614b429bf4.jpg">&nbsp;</p><p>We're concerned with three main things: the number of items inserted, the overall data quality and the number of errors in the data feeds. The more effort you put into the data quality and errors, the more products you'll get listed.

</p><p><b>Step 2: Submit a test feed</b></p><h2>Step 2: Submit a test feed</h2><p>While the standard Google Merchant Center web interface will show you errors and warnings, it won't show them all on one page and there's no immediate option to download them all in an easily digested spreadsheet. 

</p><p><img mce_src="/custom/images/medium/4f5606839aef7.jpg" height="221" width="426" src="/custom/images/medium/4f5606839aef7.jpg">&nbsp;</p><p>Therefore, the first step I'd suggest is to download your existing feed from the Data feeds page and rename it under a new name in order to create a <a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=1188998" href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=1188998">test data feed</a>. 

</p><p>On the Data feeds page click "New Test Data Feed" and upload the copy of the feed you downloaded to create a new test data feed which will allow you to check your changes and download all errors and warnings in a CSV file. </p><p><img mce_src="/custom/images/medium/4f5606826079e.jpg" height="335" width="426" src="/custom/images/medium/4f5606826079e.jpg">&nbsp;</p><p>

After a few minutes, if you click the list of errors on the Data feeds &gt; Status section, you should find an option to "Download full report". Click the link and you should receive a huge CSV file to open in Excel allowing you to search for errors and warnings. 

</p><p><img mce_src="/custom/images/medium/4f5606848285f.jpg" height="303" width="426" src="/custom/images/medium/4f5606848285f.jpg">&nbsp;</p><p>&nbsp;</p><h2>Step 3: Examine data quality&nbsp;&nbsp;</h2><p>The next step is to look at your <a target="_blank" mce_href="http://www.google.co.uk/merchants/qualityfeedback" href="http://www.google.co.uk/merchants/qualityfeedback">data quality</a>, which covers things like missing or invalid product identifiers, or long titles. 

The issues Google discovers in your feed will be separated into Critical Errors and Suggested Optimisations. </p><p>Critical Errors are obviously really bad and you must fix them quickly to prevent your feed being suspended. 

</p><p><img mce_src="/custom/images/medium/4f5614b2effc0.jpg" height="314" width="426" src="/custom/images/medium/4f5614b2effc0.jpg">&nbsp;</p><p>Typical reasons for critical errors are products that have been added without the required product identifier or GTIN, which is usually a product code or barcode. 

</p><p>Rather unhelpfully, Google doesn't inform you by email when it discovers such issues, so you'll need to check the Data quality report regularly. </p><p>It's also worth setting up an alert in Google Analytics to inform you of traffic drops from this source. 

If you click the "<a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=160161" href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=160161">How to fix</a>" links, you'll find details on how you can resolve the problem. </p><p>You'll need to work through the errors one by one, examine your feed data for similar issues, and then upload it to assess what's left to fix.</p><h2>Step 4: Examine data feed errors</h2><p>Data feed errors are the next issue to tackle. You can examine these by viewing the reports at Data feeds &gt; Status &gt; View errors. </p><p>If you need to download a copy of your XML feed to examine, you can use the link on this page and then open it up in a text editor. 

</p><p>You can also find individual errors by using Ctrl + F within the full report you downloaded in Step 2 and searching for "error". 

</p><p>The item errors report on the web interface will show any products that have errors and have been de-listed. None of these will be shown on Google Shopping or Google Ads, so you'll want to rectify these first. 

</p><p>Typical reasons for errors are "non-unique items", which are usually different products with the same product code; image URLs which contain unusual characters such as square brackets, or items with product descriptions that contain too much text.</p><h2>Step 5: Testing your changes&nbsp;</h2><p>Once you've edited your product content to resolve the issues the Google Merchant Center has flagged, you'll need to use your e-commerce platform to regenerate the feed.</p><p> 

Once you've done this, go to Data feeds &gt; Daily upload and click the "Update and fetch now" button. </p><p>After a few minutes, you should see the new data appearing in your Status report and you'll be able to work out what work is left to complete.</p><h2>Solving common errors</h2><p>Any products in your feed that throw an error won't be displayed in Google Product Search or Product Ads, so fixing these should be your top priority. 

</p><p><b>"Item too big"
</b></p><p>The <a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=1139283" href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=1139283">item is too big</a> error is caused by product descriptions which are over 10KB in size. Flash or JavaScript code, or just shedloads of text can push you over this limit, so you'll simply need to cut the length of the copy in the description field to fix it. 

</p><p><b>"Invalid URL in attribute"</b></p><p>
The <a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=160038" href="http://support.google.com/merchants/bin/answer.py?hl=en-GB&amp;answer=160038">Invalid URL in attribute</a> error is triggered by dodgy URLs and filenames present in the Google Merchant Centre feed. Typical causes for this are spaces in URLs that haven't been escaped with "%20", the presence of backslashes instead of forward slashes, the use of relative URLs (ie. file.html) and missing http:// at the start of the URL. </p><p>

<b>"Duplicate item"</b></p><p>Duplicate item errors are usually caused by product administrators inadvertently using the same product code for multiple SKUs. This is easily fixed by identifying the duplicates and adding the correct product codes, or the additional EAN/GTIN for the SKUs.</p><p><b>"Missing required attribute: title"</b></p><p>Oh dear, one of your staff has added a product without a page title, which isn't very clever, but thankfully it is easily fixed.</p><p><b>Solving common warnings
</b></p><p>Warnings won't prevent products from being listed, but they do affect your overall feed quality, so might feasibly have an impact upon ranking. It makes sense to improve these where you can.</p><p> 

<b>"Invalid UPC value"
</b></p><p>The Universal Product Code (UPC) is a US barcode based on 12 numerical digits. Check that yours meets these criteria if you're supplying one. Make sure there are no non-numerical characters present. All barcodes passed to Google get validated, and it will throw an error if it finds an invalid code, which means the product won't be displayed.</p><p><b>"Invalid string value in attribute: description"
</b></p><p>The description field in the feed contains the product copy for the item you're promoting. The usual reason for the "invalid string value" error is that the description is completely missing, or contains an invalid character. If the description is completely missing you'll also get another warning for "Missing recommended attribute: description".

</p><p><b>"Missing recommended attribute: google_product_category"
</b></p><p>The <a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en&amp;answer=160081" href="http://support.google.com/merchants/bin/answer.py?hl=en&amp;answer=160081">Google Product Category</a> is a string which tells Google Shopping how to categorise the item. It's typically something like "Media &gt; DVDs &amp; Videos" and is based on Google's taxonomy, not yours. 

</p><p>However, although it's wise to add it to every item you list it's only essential for feeds in the UK, US, Germany, Japan and France which sell products in <a target="_blank" mce_href="http://merchant-center-announcements.blogspot.com/" href="http://merchant-center-announcements.blogspot.com/">certain categories listed here</a>. 

</p><p><b>"Missing recommended attribute: product_type"
</b></p><p>Unlike the google_product_category, the product_type field is based on your site's taxonomy for the given item. You'd usually use this in conjunction with google_product_category to place the item in Google's taxonomy, and then provide additional <a target="_blank" mce_href="http://support.google.com/merchants/bin/answer.py?hl=en&amp;answer=160081" href="http://support.google.com/merchants/bin/answer.py?hl=en&amp;answer=160081">breadcrumb information</a> to further categorise the product. 

</p><p><b>"Missing recommended attribute: image_link"
</b></p><p>The image link is a recommended field to provide, so you'll need to source an image and include the URL in your feed to get rid of this notice.</p><p><img alt="" title="undefined" align="" border="" height="310" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f563f048a067.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><b>"roboted images"</b></p><p>This error occurs because there is a User-agent Disallow rule in your robots.txt file which is blocking Googlebot or Googlebot-Image from accessing the images required for the feed. To fix this add the following lines to your robots.txt file:</p><p>User-agent: Googlebot&nbsp;</p><p>Allow: /images/</p><p>User-agent: Googlebot-Image</p><p>Allow: /images/&nbsp;</p><h2>7 helpful tips for troubleshooting feeds</h2><p>1. Check the Google Merchant Center Dashboard regularly to ensure your feeds are working optimally. Google won't tell you when your products or feed gets de-listed and you'll lose money if you don't check regularly. 

</p><p>2. Keep a close eye on the <a target="_blank" mce_href="http://merchant-center-announcements.blogspot.com/" href="http://merchant-center-announcements.blogspot.com/">Google Merchant Center Announcements blog</a>. This is where you'll find more information on forthcoming changes to feed requirements and how they might affect you. </p><p>

3. Track the revenue you're getting from Google Merchant Centre feeds using Google Analytics campaign tracking parameters in your URLs. You can create dashboards (above), custom reports, advanced segments and alerts to help you can an eye on things. 

</p><p>4. If you need help diagnosing problems with your feed, check out the <a target="_blank" mce_href="http://groups.google.com/a/googleproductforums.com/forum/#!forum/merchant-center" href="http://groups.google.com/a/googleproductforums.com/forum/#!forum/merchant-center">Google Merchant Center forums</a> at Google Groups. 

</p><p>5. The errors and warnings which apply to you will depend on what you sell, and in which countries you operate. You'll need to check the guidelines at <a target="_blank" mce_href="http://support.google.com/merchants/?hl=en-GB" href="http://support.google.com/merchants/?hl=en-GB">Google Merchant Center Help</a> to find out which ones matter to you. 

</p><p>6. You can find GTINs that Google recognises by searching for the product in Google Shopping and clicking the "Compare Prices" button which usually appears on the first result. Scroll to the bottom and you should find the EAN you need.</p><p>7. Dodgy GTINs are among the trickiest issues to solve and your item will be rejected if you supply an invalid code. Fortunately, you can validate them yourself directly within your platform using <a target="_blank" href="https://github.com/charithe/gtin-validator/blob/master/gtin_validator.py">code like this</a>.&nbsp;</p><p>8. Provide as much detail as possible and make sure content editors always maintain high standards of data quality. Miss out your EANs, for example, and you'll get far less exposure. &nbsp;</p><p><b>Why bother?</b>&nbsp;</p><p>Here's what can happen to your performance if you optimise properly! A 200%+ performance boost. Simply fixing the errors and warnings and improving taxonomy helps increase the clicks.&nbsp;</p><p>We're now seeing a huge increase in revenues from this channel which is making a massive financial contribution. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="106" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f5f463c7008c.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=219&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_219]]></link>
			</item>
			<item>
				<title><![CDATA[Using Google Analytics ecommerce data for ABC/Pareto analysis]]></title>
				<description><![CDATA[Performing an ABC or Pareto analysis on your e-commerce sales can shed light on several interesting things about your business.

<p>Vilfredo Pareto's eponymous Pareto principle is a rule of thumb applied to many things in business, one of which is that 80% of revenue will come from 20% of your product range.&nbsp;</p><p>Knowing which 20% of your products are having the greatest impact on your revenues can help you reduce the revenue you lose to stock outs and help you optimise your product sales for the slower turning lines.</p><p>It's not directly possible to do a Pareto analysis in Google Analytics, but you can use the Google Analytics Data Feed Query Explorer to extract your annual sales data and pull it into Excel for further analysis.&nbsp;</p><p><b>Step 1: Fetching the data</b>&nbsp;</p><p>Log into the Data Feed Query Explorer and create a query to fetch the product name and item revenue for every product you've sold over the past 12 months, and order the results by descending item revenue.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="355" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f4d42a434cc5.jpg">&nbsp;&nbsp;</p><p>You can save time by <a href="http://techpad.co.uk/custom/images/medium/4f4d42a434cc5.jpg">clicking here</a> and then authenticating your Google Analytics account. If you highlight the data produced with your cursor, you can just copy and paste it from the Data Feed Query Explorer straight into Excel.&nbsp;</p><p><b>Step 2: Sorting the data</b></p><p>Now that we've got our revenue data for all of the products we've sold over the past year, we need to count the number of products and split them into three classes, A (the top 20% of sales), B (the next 75% of sales) and C (the bottom 5% of sales).&nbsp;I'd recommend placing each class on its own sheet so you can go over them more easily. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="272" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f4d4709a5c32.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>You should find that approximately 80% of your revenue comes from the top 20% of products sold (it was 75% in the case of my site), while the other two classes (80% of your stock) make up the remaining 20% of your revenue.&nbsp;&nbsp;</p><p><b>Step 3: Analysing the class data</b></p><p><b></b>The products in class A are the ones that are currently of the greatest importance to your revenue.&nbsp;These are the ones you need to keep a really close eye on in terms of your&nbsp;<a mce_href="http://techpad.co.uk/content.php?sid=209" href="http://techpad.co.uk/content.php?sid=209">inventory control</a>&nbsp;as&nbsp;<a mce_href="http://techpad.co.uk/content.php?sid=183" href="http://techpad.co.uk/content.php?sid=183">stock outs will lose you sales</a>.&nbsp;</p><p>However, if anything, the really interesting stuff lies within the B and C classes. If you spot products in here that you'd expect ought to really be fast-moving products that shift in large quantities worthy of class A, then you've spotted a potential problem.&nbsp;Are they priced too high? What's stopping your customers purchasing them as often as you'd expect?&nbsp;</p><p>If everything is definitely in order regarding pricing and other on-site issues, then perhaps you could reduce your inventory levels of these slower moving items, make them special order items or get them drop-shipped to free up working capital?&nbsp;</p><p>The other really useful information lies in what you can't see. Google Analytics will obviously only tell you about the products you <i>have</i> sold. </p><p>If you compare the total number of products you've exported to the actual number of products in your range you may spot a number of products that haven't sold at all - so called class D items. In this case, there's something very wrong and you definitely ought to consider clearing these, unless they're simply range completers.</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=218&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_218]]></link>
			</item>
			<item>
				<title><![CDATA[Building analytics tools with the Google Core Reporting API part II]]></title>
				<description><![CDATA[This quick guide explains how you can create a flexible table structure for displaying data exported from the Google Analytics Core Reporting API. 

<p>In part one of this series of blog posts on the Google Analytics Core Reporting API - <a mce_href="http://techpad.co.uk/content.php?sid=198" href="http://techpad.co.uk/content.php?sid=198">Building analytics tools with the Google Core Reporting API part I</a> -&nbsp; I explained how to perform authentication with OAuth 2.0 and how to access data objects.&nbsp;</p><p>The next step is to display your data. </p><p>However, if you're creating different queries to run which have varying numbers and types of metric and dimension selected, you need a flexible way of formatting data without the need to code a new table each time you modify your API query. </p><p>The Smarty templating engine for PHP is ideal for this.&nbsp;</p><p><b>Step 1: Install Smarty and set it up</b></p><p>Firstly you'll need to install Smarty and get it set up so you can use it within your Core Reporting API application. You can download it from www.smarty.net and check the excellent Smarty Crash Course for some tips on set-up and basic usage.&nbsp;</p><p>Once you've set it up, you'll want to assign a title variable to pass to Smarty: $smarty-&gt;assign('title','Data for ');</p><p><img alt="" title="undefined" align="" border="" height="283" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f5867f97ecaf.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p>Then you need to get the column headers, which are your metrics and dimensions, and add them to an array to pass to Smarty so we can use them as the table headers: $smarty-&gt;assign('headers',$data['columnHeaders']);</p><p>The rest of the data can be passed to Smarty as $data: $smarty-&gt;assign('data',$data); and then you can send it all to the display template with $smarty-&gt;display('../templates/table.tpl');</p><p><b>Step 2: Create your flexible table template</b></p><p>In order to get your content to display clearly, with the right column headings and the right number of columns, we need a flexible structure that works for any combination of metrics and dimensions.&nbsp;</p><p>Create the basic table structure using the standard  tags and then create a loop construct within your first set of  table row tags to add the headings based on the selected dimensions and metrics. &nbsp;</p><p><img alt="" title="undefined" mce_src="/custom/images/medium/4f576f0bd7556.jpg" align="" border="" height="254" hspace="" vspace="" width="426" src="/custom/images/medium/4f576f0bd7556.jpg"></p><p>The next step is to loop through the actual data. I used a foreach to loop over all of the results and display them in the appropriate table cells.&nbsp;</p><p>There are some tweaks that are worth making to make the data more presentable. </p><p>I used the Smarty cycle value to add a class "on" or "off" to each table row and then added CSS to change the colour to create a zebra-table effect of alternating row colours.&nbsp;</p><p><img mce_src="/custom/images/medium/4f586f47e3780.jpg" height="360" width="426" src="/custom/images/medium/4f586f47e3780.jpg">&nbsp;</p><p>I also used is_numeric and stristr to check to see whether the value was a string or an integer and rounded the values that had lots of trailing decimal places, and truncated long strings, such as URLs, to make the data a bit cleaner. </p><p>Add some CSS to style it up and you've got a quick and easy way to 
display lots of data from the Core Reporting API, without the need to 
edit anything other than your original query. &nbsp; <br></p><p><img alt="" title="undefined" align="" border="" height="148" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f586826099b2.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>Next time I'll explain how you can use refresh tokens to create applications that can run without user interaction. &nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=213&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_213]]></link>
			</item>
			<item>
				<title><![CDATA[Turn Google Analytics into an inventory profiling system]]></title>
				<description><![CDATA[Want to get inventory profiling data on your stock into Google Analytics so you can analyse it? Here's how I did it with a server-side event tracking hack.

<p>Stock management tends to be quite basic for those of us using standard e-commerce platforms without expensive warehouse integration systems.</p>

<p>It relies upon two key bits of data held in the e-commerce platform's database: the current stock holding for each product, and the low-stock level for each product.</p>

<p>When an item is sold, the stock holding goes down according to the number of units sold. Each product is then re-ordered when its stock level reaches its low-stock level or re-order point (ROP).</p> 

<p>The stock holding level is manually increased when the ordered goods arrive from the supplier and stock levels are replenished to the maximum stock level.</p>

<p>This technique works but its success is dependent upon a number of things, and there are various business considerations to take into consideration to ensure it works optimally.</p><p>Here's a textbook representation of what happens to stock levels. &nbsp;&nbsp;</p><p><img alt="" title="undefined" align="" border="" height="314" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f23d7f84669b.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p>

<h3>The problem?</h3>
<p>Well, two main things can go wrong. </p><p>You can run out of stock because your stock holding isn't large enough to meet the demand, or you can have a low-stock level which is too low, which means you run out of stock while waiting for the goods you've re-ordered to arrive.</p>

<p>These things need checking continually, because demand for products can rise (and fall), causing you to run out of popular products (or have a surplus of slow sellers you need to turn).</p>

<p>I've explained before how I have used Google Analytics to <a mce_href="http://techpad.co.uk/content.php?sid=183" href="http://techpad.co.uk/content.php?sid=183">identify the revenue you lose to stock-outs</a>, and it's well worth implementing this if you suspect stock control needs improving.</p>

<p>However, looking at stock-outs only gives you part of the picture. </p><p>What you really want to see, is how close you get to your buffer inventory, how much stock you have, what the demand is like, and how much working capital you have tied up in your stock in relation to sales.</p>

<p>Most e-commerce platforms don't tell you this, and our systems don't report it, so I spent a day devising a hack to obtain the data and pull it into Google Analytics for monitoring, reporting and analysis.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="232" align="" title="undefined" src="/custom/images/medium/4f7dbb0c9bc4d.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><h3>What will this hack provide?</h3><div><ul><li>Timelines showing how your total inventory level and value changes over time.</li><li>Timelines showing how many categories, subcategories, products and SKUs you have.</li><li>Timelines showing how many stocked and drop-shipped SKUs you have.</li><li>Timelines showing how many customers and newsletter subscribers you have.</li><li>Detailed data on the number of subcategories, products and SKUs per category.</li><li>The value and inventory size of each category on your site.</li><li>The total inventory, buffer inventory and inventory value for every product on your site.</li><li>Plus any other timeline-based daily metrics you fancy injecting into GA.&nbsp;</li></ul></div>

<h3>Step 1: Setting up server-side analytics</h3>
<p>In order to obtain data on these things you need to query the database at a particular time each day and send the data to Google Analytics.</p><p> However, that's not feasible using the standard client-side tracking code - you need to do it on the server-side from a command-line application. <br></p><p>To achieve this I developed a command-line application in PHP which runs on the PHP-CLI and queries a SQL database to obtain the metrics required.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="163" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f24246c4df4b.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>It then injects them into Google Analytics using the excellent&nbsp;<a mce_href="http://techpad.co.uk/content.php?sid=205" href="http://techpad.co.uk/content.php?sid=205">PHP-GA</a> class. If you've not used this before you can get some general usage tips from my post on the hack I made&nbsp;for testing a <a mce_href="http://techpad.co.uk/content.php?sid=205" href="http://techpad.co.uk/content.php?sid=205">cookie-less Google Analytics implementation</a>.</p><p>Using a command-line application with server-side analytics allows you to run the code from a server and can <a mce_href="http://techpad.co.uk/content.php?sid=195" href="http://techpad.co.uk/content.php?sid=195">bypass the 10 event limit</a> imposed for the client side GATC.&nbsp;</p><p>You could also use <a mce_href="http://techpad.co.uk/content.php?sid=186" href="http://techpad.co.uk/content.php?sid=186">SSGA server-side Google Analytics</a> if you prefer, but it's not been updated for a while and, annoyingly, it encodes spaces in event category, action and label strings.&nbsp;</p><p><span class="Apple-style-span" style="font-size: 14px; font-weight: bold; ">Step 2: Obtaining aggregate daily totals</span></p>
<p>The first thing I wanted to obtain was aggregate daily totals on various metrics to give an overview on the inventory not provided by our e-commerce platform. </p><p>This includes metrics like the daily levels for: total categories, total products, total SKUs, total stocked SKUs, total drop-shipped SKUs, total inventory units and total inventory value. <br></p>

<p>I wrote a PHP class containing a series of functions which ran SQL queries against the e-commerce platform's database and returned the required data in variables I could pass to GA and echo to the command line output.</p><p>If anything, this was the most complicated bit, due to the nature of some of the joins required to query the database. These will obviously vary according to your platform, so I've skipped them out here. &nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="274" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f2424e54203a.jpg" onmouseover="undefined" onmouseout="undefined"></p><h3>Step 3: Configuring your events</h3><p>Once I had the metrics, I then used server-side event tracking to add the data to GA to a separate profile - the latter point is important, for reasons I'll explain in a minute.</p><p>Here's the format I used for the PHP-GA events to ensure data is placed in the correct place in GA for easy analysis.&nbsp;These events place all data in an event category called 'Aggregate daily totals'. Drilling-down to action and label levels gives you access to the rest of your data.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="257" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f23e5f9b889d.jpg">&nbsp;</p><p><b>Categories</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Category','12',12).<br><b>Goal:</b>&nbsp;Monitors the total number of categories over time.<br></p><p><b>Products</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Products','1234',1234).<br><b>Goal:</b>&nbsp;Monitors the total number of products over time.<br></p><p><b>SKUs (stocked)</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','SKUs (stocked)','12345',12345).<br><b>Goal:</b>&nbsp;Monitors the total number of SKUs stocked over time.<br></p><p><b>SKUs (direct)</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','SKUs (direct)','1234',1234).<br><b>Goal:</b>&nbsp;Monitors the total number of drop-shipped SKUs over time.<br></p><p><b>SKUs (out of stock)</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','SKUs (out of stock)','123',123).<br><b>Goal:</b>&nbsp;Monitors the total number of out of stock SKUs over time.<br></p><p><b>Inventory units</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Inventory units','1234567',1234567).<br><b>Goal:</b>&nbsp;Monitors the total number of units of stock held over time.<br></p><p><b>Inventory value</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Inventory value','8787878',8787878).<br><b>Goal:</b>&nbsp;Monitors the total value of units of stock held over time.<br></p><p><b>Customers</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Customers','1234567',1234567).<br><b>Goal:</b>&nbsp;Monitors the total number of customers over time.<br></p><p><b>Newsletter subscribers</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Newsletter subscribers','123456',123456).<br><b>Goal:</b>&nbsp;Monitors the total number of newsletter subscribers over time.</p><p>Here's an example of the code required to create the new session in PHP-GA and to send the event tracking data. Again, there's more information and sample code in <a href="http://techpad.co.uk/content.php?sid=205">my other post on PHP-GA</a>.&nbsp;</p><p>Providing you're sending fewer than 499 events in a single PHP-GA session, you should be able to use a single&nbsp;$tracker-&gt;trackPageview($page,$session,$visitor);&nbsp;call. </p><p>Send more and you risk hitting the 500 hit limit for a session, and you'll need to split events over multiple sessions in the same script.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="282" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f22bdb9368f4.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>Echoing the output of the application to the terminal is useful during testing because it allows you to see that the data are being obtained correctly and gives you the opportunity to look for PHP-GA's errors, since PHP-CLI applications don't run through Apache and errors, warnings and notices don't appear in its error logs.</p><p>Once you've sent some test data, you should see it appearing in the GA web interface within about 10 minutes. </p><p>It's then possible to look at the charts produced showing the daily 
event values to see how they change over time. Some of the other totals obviously won't be usable, but that's easily fixed by creating custom reports.</p><h3>Step 4: Analysing inventory by category</h3>

<p>Now that I had an overview of the entire inventory, the next thing I wanted to examine was the inventory at a product level.&nbsp;</p>

<p>The data should be useful for finding out which categories were underperforming and should show what return we were getting from the stock held, when you compare sales revenue to inventory.</p>

<p>How many products and SKUs were in each category? How much stock were we holding? How much working capital was tied up in stock? What return did we get from our inventory for the category?</p>

<p>If we had £2000 of working capital tied up in our stocks of purple mohair ties but monthly sales were only £100, did we really need so much stock? Would it be better to drop-ship these instead?</p><p>Extracting these data is achieved in similar ways, but obviously involves a bit of looping and for my e-commerce platform some of the database queries involved some complicated joins and concatenation.</p><p>However, the principle is easy. First you need to get your list of categories, then for each category you need to obtain the total number of products, SKUs, inventory held and its value. Here's an example of the event tracking code used.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="135" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f243efb86545.jpg"></p><p><b>Subcategories in category</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Subcategories in category','Tablet PCs',3).<br><b>Goal:</b>&nbsp;Monitors the total number of subcategories in a category over time.<br></p><p><b>Products in category</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Products in category','Tablet PCs',123).<br><b>Goal:</b>&nbsp;Monitors the total number of products in a category over time.</p>

<p><b>SKUs in category</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','SKUs in category','Tablet PCs',3234).<br><b>Goal:</b>&nbsp;Monitors the total number of SKUs in a category over time.<br></p><p><b>Inventory units in category</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Inventory units in category','Tablet PCs',39393).<br><b>Goal:</b>&nbsp;Monitors the total number of units of stock in a category over time.</p><p><b>Inventory value in category</b><br><b>Event format:</b>&nbsp;_trackEvent('Aggregate daily totals','Inventory value in category','Tablet PCs',123456).<br><b>Goal:</b>&nbsp;Monitors the total value of stock in a category over time.</p><p>If you have lots of data to send, consider using sleep(1) to pause for a second between the POSTing of data to prevent hammering the GA servers with a shed-load (that's English for a lot) of traffic all at once.&nbsp;</p><p>You'll also need to ensure you use PHP-GA to create a new session for each set of related events you send, otherwise you'll hit the 500 hits per session limit and execution of the script will stop.&nbsp;</p><p>It's worth making sure that error messages are set to display to standard out because you may get "MySQL has gone away" timeout messages if your data takes a long time to crunch. Opening a new connection for each chunk of data should solve this. &nbsp;</p><h3>Step 5: Sending product-level data</h3><p>Now that we've done with collecting the aggregate data and the category-level data, it's time to do the bulkier task of obtaining the product-level data which provides your actual inventory profile timelines.&nbsp;</p><p>The principle for this bit is the same as for the category-level data. You run a SELECT query against your database to get a full list of your SKUs and return the product name, SKU code, cost price, quantity of stock being held and then create a while loop.&nbsp;</p><p>Within the while loop you need to create a new PHP-GA session for each SKU returned and then send four events containing the data we want to send to Google Analytics. </p><p>It's vital to create a new session for each one, because you'll otherwise hit the 500 hit limit in no time. You'll also want to use a sleep() function to minimise the speed at which data is sent to Google's servers.</p><p>Since we're adding a bit more data to these, and allowing more drilling-down, these data are going in separate event categories.&nbsp;</p><p><b>Inventory units<br>Event format:</b>&nbsp;_trackEvent('Inventory units','Apple Macbook Pro 15','AMBP15',5).<br><b>Goal:</b>&nbsp;Monitors the total holding of a SKU over time.</p><p><b>Inventory value</b><br><b>Event format:</b>&nbsp;_trackEvent('Inventory value','Apple Macbook Pro 15','AMBP15',4500).<br><b>Goal:</b>&nbsp;Monitors the total value of SKU inventory over time.<br></p><p><b>Re-order level</b><br><b>Event format:</b>&nbsp;_trackEvent('Re-order level','Apple Macbook Pro 15','AMBP15',1).<br><b>Goal:</b>&nbsp;Monitors the re-order or low-stock level over time.</p><p><img alt="" border="" hspace="" vspace="" width="426" height="285" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f23db975d440.jpg" onmouseover="undefined" onmouseout="undefined"></p><h3>Step 6: Automating data collection</h3><p>In order for the data to be accurate you need to ensure that the queries are only run once per day.&nbsp;</p>

<p>I configured a cron job to run my script as a scheduled task on my Linux server every night at one minute past midnight with this command: 01 00 * * * php /var/www/stockprofiler/profiler.php</p>

<p>Every morning when I check GA, I have fresh data from the previous day. I don't need to touch the code again - it just keeps sending me new data on the inventory just as the client-side code does.&nbsp;</p><h3>Step 6: Accessing your inventory data</h3><p>Once you've followed the above steps, you'll be able to access the data in your new profile via the following event categories.&nbsp;You can drill-down among them to see aggregate totals for each day, category or product.</p><p><img alt="" title="undefined" align="" border="" height="218" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f23d6b27eac4.jpg">&nbsp;</p><p>Don't forget that because we're sending daily totals to GA, the only field that will really make sense if the event value and the timeline for the metric. </p><p>The total event value metrics will be calculated based on the combined sum of daily events, so won't mean much.&nbsp;It's best to create some custom reports.&nbsp;</p><p><img alt="" border="" hspace="" vspace="" width="426" height="202" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f24495c94cc9.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><h3>Handy tips</h3><ul><li>Put this data in a <a href="http://support.google.com/googleanalytics/bin/answer.py?hl=en&amp;answer=55486">separate Google Analytics profile</a> to prevent the large quantity of hit level data sent pushing you over your data limit. It would be nice to have the data in the same account as your web data, as you'd then be able to compare web metrics to inventory metrics, but there are risks to that if you have a large site.</li></ul><ul><li>Don't send more than 10 million bits of hit level data per month, otherwise you'll hit Google Analytics'&nbsp;<a mce_href="http://support.google.com/googleanalytics/bin/answer.py?hl=en&amp;answer=1070981" href="http://support.google.com/googleanalytics/bin/answer.py?hl=en&amp;answer=1070981">data limit</a>. If you have a big product range, calculate the number of events your script will be firing to determine whether this could be an issue.</li></ul><ul><li>Don't exceed more than 1 million hits per day, otherwise your data will only be refreshed once a day, and you'll exceed your monthly data limit.</li></ul><div><img alt="" title="undefined" align="" border="" height="263" hspace="" vspace="" width="426" src="http://techpad.co.uk/custom/images/medium/4f22d44a24837.jpg">&nbsp;&nbsp;</div><ul><li>Use the new real time reports in Google Analytics 5 to get an idea of the amount of data being sent and the rate, and to check that everything is working as intended during testing.</li></ul><ul><li>If you're using this hack with Google Analytics Premium there is no data limit, so theoretically you could use this with quite a big product inventory.&nbsp;</li></ul><ul><li>Don't send more than 500 bits of hit level data in a single session. If you're looping over data, use PHP-GA to start a new session in each loop, which will increase the number of sessions and prevents you hitting the <a href="http://code.google.com/apis/analytics/docs/tracking/eventTrackerGuide.html">500 hit limit</a>.&nbsp;</li></ul><ul><li>Use a <a href="http://php.net/manual/en/function.sleep.php">sleep() function</a> to pause the sending of session data by your script for a second to prevent it hammering the GA servers.&nbsp;</li></ul><ul><li>Make sure your <a href="http://en.wikipedia.org/wiki/Cron">cron job</a> only fires once a day, as most of these are daily totals which will be ruined if you inadvertently send the data multiple times.</li></ul><ul><li>Create custom reports to make the data more meaningful, since some of the metrics won't apply with this hack.&nbsp;</li></ul>


]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=209&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_209]]></link>
			</item>
			<item>
				<title><![CDATA[Monitoring operations error rates and financial losses in Google Analytics]]></title>
				<description><![CDATA[To help drive improvements in operations service quality and reduce financial losses, you'll need to know how many damages and faulty items are being replaced free of charge and how many customers are suffering from orders with missing items or picking errors. Thankfully, it's quite easy to track this in Google Analytics using a fairly simple back-end hack. 

<div>This little hack allows you to create a dashboard in Google Analytics which shows how many items you've given away free of charge to customers in the event of service quality failures, such as warehouse picking errors, transit damages and goods that have failed under warranty.</div><div>&nbsp;</div><div>Not only will you be able to see the financial costs of this, you'll also be able to look for trends, and examine the underlying data to reveal useful facts, like which products are most frequently being picked incorrectly or which products most often arrive smashed.&nbsp;</div><div>&nbsp;</div><div>If your ecommerce platform is already set-up with Google Analytics ecommerce tracking on the back-end, to allow you to record ecommerce data for orders taken by telephone, setting this up and creating the dashboards should take you less than an hour. &nbsp;</div><div><h3>Adding the data to Google Analytics</h3></div><div>Assuming you've already got a system in place which allows you to take orders on the back-end of your ecommerce platform, the first step is to add a simple select menu to your back-end which records the reason why you're providing a given product as a free of charge replacement.&nbsp;</div><div>&nbsp;</div><div>The option values here are going to become the event tracking actions in Google Analytics, so you'll want to choose them carefully. I went with the following options. </div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="100" align="" title="undefined" mce_src="/custom/images/medium/4f1878a550a1c.jpg" src="/custom/images/medium/4f1878a550a1c.jpg" onmouseover="undefined" onmouseout="undefined"></div><div>&nbsp;</div><div>When the form is submitted, you'll need to write a little snippet of server-side code to grab the selected value from the menu and get the name of the product and its value. Since I'm sending the data to Google Analytics using the ecommerce tracking methods, I already had access to these data.&nbsp;</div><div>&nbsp;</div><div>In your tracking code, you now need to grab that information and use your server-side language to write a single line of code into your Google Analytics tracking tag which is based on this format (but with variable data populating the event action, event label and event value fields).&nbsp;</div><div>&nbsp;&nbsp;</div><code>_gaq.push(['_trackEvent','Free replacement','Damaged item','iPad 2', 429]);</code><div>&nbsp;</div><div>In the above code I've used "Free replacement" as the event category, added the value from the select menu in the event action, the product name in the event label and the rounded value of the product in the event value field. The latter bit is important, since you can't use floats in the event value field. </div><div>&nbsp;</div><div>That's basically all you need to do in order to get the data you need into Google Analytics! Dead easy.</div><div><h3>Creating the dashboards</h3></div><div>To access the data easily it makes sense to take advantage of the excellent new dashboard features in Google Analytics. I used the widget feature to create two widgets for each event action (ie. Damaged item, Picking error, Faulty under warranty etc).</div><div>&nbsp;</div><div>One of the widgets you create needs to record the Total Events metric and should filter to only show the Event Category which is an exact match for the Event Action you added to your code (ie. Damaged item). I also created an additional widget to provide an overall count of total replacements which filtered by the Event Category "Free replacements".</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="246" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f1878a6c3dbb.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div>Once you've worked through all of your event actions and created a widget to report the total events for each one, the next step is to create widgets for the total value. These will give you a rounded approximation of the total value you've spent on replacing the items free of charge due to your various service failings.</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="243" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f18889635526.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div>Again, just work through each of the event actions that you had in your original code and you should end up with about 12 widgets, which also happens to be the maximum number you can store on a given dashboard in GA 5.&nbsp;</div><div><div><h3>Using the data</h3></div></div><div>One other potentially useful dashboard to create would be a report showing which products are arriving broken, failing under warranty or being picked incorrectly. </div><div>&nbsp;</div><div>To create this, you'd be best using the Table option on the widget tool and opting to display the event label and adding your desired filter, which should then generate a list of products for the given event action.</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="293" align="" title="undefined" src="http://techpad.co.uk/custom/images/medium/4f1878a41415a.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div>Now all that remains is to get your staff to use the field, wait for the data to flow in, and then give the warehouse staff a ticking off when the error rate rockets or buy them a case of beer when things improve markedly.</div><div>&nbsp;</div><div><img alt="" border="" hspace="" vspace="" width="426" height="303" align="" title="undefined" src="/custom/images/medium/4f3a11b9431d1.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</div><div>&nbsp;</div><div>At the moment, you can't export the dashboard to PDF, mail them as scheduled reports or do much else, but they're nonetheless pretty handy for keeping an eye on financial losses and can help drive improvements if you utilise the data well.&nbsp;</div>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=208&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_208]]></link>
			</item>
			<item>
				<title><![CDATA[Developing a cookie-less Google Analytics implementation]]></title>
				<description><![CDATA[Unless you've been buried under a rock for the past year, you'll know that it will soon be a legal requirement to get website visitors to opt-in to be tracked using cookie-based analytics. 

<p>Google and the other analytics solution providers have been pretty quiet on the subject of the new <a mce_href="http://techpad.co.uk/content.php?sid=174" href="http://techpad.co.uk/content.php?sid=174">EU cookie legislation</a>. </p><p><a mce_href="http://techpad.co.uk/content.php?sid=199" href="http://techpad.co.uk/content.php?sid=199">Avinash Kaushik has confirmed</a> that analytics providers have been discussing the legislation, but hasn't said whether they have a solution to the problem, and if they do, what it will entail.&nbsp;</p><p>If you're affected, your options are to get users to opt-in to being tracked using cookies (in which case you can kiss goodbye to 90% of your web analytics data and rely on sampling), do nothing in the likely event that the ICO don't bother to prosecute you simply for using GA, or switch to a server-side tracking system which doesn't rely on cookies.&nbsp;</p><p>While I'm aware of other cookie-less tracking systems, I haven't used any since the pre-GA/Webtrends days.&nbsp;</p><p> Personally, I'd be extremely surprised if they came anywhere close to the functionality of Google Analytics, and like many other people in the industry, I've got data in the tool that I want to keep and features I rely upon for my work. </p><p>GA does what I need it to do, and it's tightly integrated into my sites so I can capture additional data to help me make the right decisions.&nbsp;</p><p>If browser manufacturers aren't going to step-in to allow this issue to be handled on the browser side, the best solution for me seems to be the development of a <a mce_href="http://techpad.co.uk/content.php?sid=186" href="http://techpad.co.uk/content.php?sid=186">server-side Google Analytics</a> tracking system. </p><p>That could be one that has official backing, or one that's been built from scratch to help overcome the legislation in a legal and responsible manner.</p><p><img alt="" title="undefined" mce_src="/custom/images/medium/4ccbfacb53be3.jpg" height="285" hspace="" border="" vspace="" width="426" align="" src="/custom/images/medium/4ccbfacb53be3.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><p><span class="Apple-style-span" style="font-size: 14px; font-weight: bold; ">Server-side Google Analytics?</span></p><p><b></b>The current Google Analytics tracking solution is a client-side system and the JavaScript code is executed by the browser. </p><p>Tracking data is sent to GA via GIF image requests generated by the code, with certain items of data, such as timestamps and unique identification hashes, being stored in a number of first-party cookies in the visitor's browser.</p><p>Google does not yet provide a cookie-less or server-side alternative to this client-side tracking system, although its mobile tracking code comes close. </p><p>I'd be really surprised if its engineers weren't working behind the scenes on a server-side API. Indeed, the client-side code probably already interfaces with something a server-side solution could connect to as well.</p><p>Thankfully, given the lack of an authorised API, there are at least two fairly robust solutions which achieve the same thing: Server-Side Google Analytics (SSGA) and PHP-GA.&nbsp;</p><p>These are both PHP classes which pass similar data back to the GA server by faking the GIF requests, which trick Google Analytics into thinking the data is coming from a client-side tracking tag. </p><p>While some things don't work, and while some actions are harder to track and require more coding effort, they're both actually quite decent and it is possible to get quite a bit of the core tracking data into GA without relying on cookies.</p><h3>Server-side GA isn't cookie-less by default...</h3><p>You can use either SSGA or PHP-GA for this.&nbsp;Both work in very similar ways. </p><p>I've used SSGA on a couple of projects and it works really well, but unlike PHP-GA it hasn't been under active development for quite a while (since April 2009) and it supports fewer features.&nbsp;</p><p>PHP-GA is more modern (it's written in fully namespaced OOP PHP), it supports pretty much all of the main features (including new ones like trackSocial) and is probably the best choice of the two.</p><p>It is server-side, rather than client-side, so the code is hidden from source code viewers and is triggered by PHP on your server, however, it <i>can</i> use cookies for some features. They're just created by PHP, rather than by JavaScript.</p><p>It hasn't been designed to be a cookie-free alternative to GA. It's been designed to replicate the functionality of Google Analytics ga.js JavaScript tracking code in PHP.&nbsp;As a result, if you use it as-is, it could create cookies. Most of the main features don't use cookies, though.</p><h3>Example 1: Basic page tracking</h3><p>For really basic pageview tracking you can use the code below. Don't forget to replace your own UA profile ID, otherwise you'll fill my test account with your data!</p><p><img alt="" title="undefined" height="" hspace="" border="" vspace="" width="" align="" src="http://techpad.co.uk/custom/images/medium/4f048a0359093.jpg" onmouseover="undefined" onmouseout="undefined"></p><p>This example simply adds the user IP address (required by GA but not shown or accessible) the user agent (ie. Windows Vista, Internet Explorer 6) and the details on the page title and file accessed. (Use REMOTE_ADDR, not REMOTE_ADDRESS, as I stupidly did!)</p><p>You can pass additional data to GA using the Visitor() function, which I'll explain in more detail later. This code doesn't set any cookies whatsover and will provide only basic tracking.&nbsp;</p><h3>Example 2: Event tracking</h3><p>Event tracking, probably the best overall feature of Google Analytics, is also very easy to achieve and again doesn't use any cookies. </p><p>You simply call the GoogleAnalytics\Event() function and then pass it the required data using setCategory(), setAction(), setLabel() and setValue() - even the <a mce_href="http://techpad.co.uk/content.php?sid=187" href="http://techpad.co.uk/content.php?sid=187">new opt_noninteraction feature</a> is supported via setNoninteraction().</p><p>The data can then be passed to the tracker using trackEvent(). Interestingly, the client-side version of GA prevents you from sending more than 10 events at once, but <a mce_href="http://techpad.co.uk/content.php?sid=195" href="http://techpad.co.uk/content.php?sid=195">you can send 20 or more simultaneously</a> with both PHP-GA and SSGA. &nbsp;</p><p><img alt="" title="undefined" height="223" hspace="" border="" vspace="" width="426" align="" src="http://techpad.co.uk/custom/images/medium/4f04a74fe8f69.jpg" onmouseover="undefined" onmouseout="undefined">&nbsp;</p><h3>Example 3: Ecommerce tracking</h3><p>Ecommerce tracking works much like the client-side equivalent. First you need to populate the order ID with a random number which is used as the transaction ID. Then you call Item() and set the orderId, the SKU, the name, quantity and price.</p><p>You can then create the transaction, pass the items, the basket total and any details you have on the customer location and shipping charges and it populates the ecommerce tracking data in exactly the same way as the client-side version. Again, no cookies are used.</p><p><img alt="" title="undefined" height="367" hspace="" border="" vspace="" width="426" align="" src="http://techpad.co.uk/custom/images/medium/4f04af649cb6c.jpg" onmouseover="undefined" onmouseout="undefined"></p><h3>Other features</h3><p>There are many more things you can do with PHP-GA, including passing additional visitor data (such as screen resolution, Flash version, Java enabled etc), setting custom variables (with cookies), and using trackSocial.&nbsp;&nbsp;&nbsp;</p><p>This only really scratches the surface of testing what you could do with PHP-GA without the need to use cookies, and what you'd probably need to do to get close to the full features sans cookies.</p><p>Granted, it falls short of client-side GA if you don't use cookies, but it provides the basics of page tracking and ecommerce tracking which could be enough to get by if the worst does happen.&nbsp;</p><p>Sadly, it isn't capable of recognising repeat visitors, presumably because GA only uses the ID stored in the __utma cookie, and not a combination of other visitor features. &nbsp;</p><p>It's not going to solve every problem, but it could record most activities without cookies and it's&nbsp;certainly going to be a lot better than having 90% of your data missing. Obviously it needs more work, though...&nbsp;</p>]]></description>
				<link><![CDATA[http://techpad.co.uk/content.php?sid=205&amp;utm_source=TechPad_website&amp;utm_medium=RSS&amp;utm_campaign=Item_205]]></link>
			</item>
	</channel>
</rss>
