I'm trying to find the best approach for analyics on 3rd party JavaScript widgets - i.e. tools and content that is distributed to any number of arbitrary users, who include the widgets as HTML snippets with tags.
On the same domain
Note that the widgets do not load into an iframe element that has a document loaded from the external site. Instead, they load content into the DOM of the host page - i.e. they are treated as being on the same domain as the host.
Analytics for a fragment of the host page
So, essentially, I want to track stats (such as widget views, user clicks and custom interactions within the widget), but I only want to track stats for the fragment of the host page that is the widget. I don't want to track clicks on the host page that are outside the widget.
I want the stats to be collated together, so that stats for the widget on site A will be aggregated with those of the widget on site B and site C, etc.
Questions
Is it possible to use Google Analaytics in a custom way that satisfies these requirements? Or is it not possible to separate GA from the rest of the data collected on the host page?
If it is possible to use Google Analytics, then will there be a problem if the host page already uses GA (with a different GA profile ID), or is it possible to keep them safely apart?
Are there any other analytics packages out there that are properly suited to widget stats tracking, to meet these requirements?
Or, how else would you approach the problem of obtaining stats for these widgets?
GA can be used for this, though since it is a free tool, it is a bit limited compared to the other tools out there. Example of other tools out there are Yahoo Web Analytics (YWA), Omniture SiteCatalyst, and Webtrends.
Most of the tracking tools out there have the ability to do custom link and "event" tracking. Basically what you would do is lookup the necessary snippet of code for custom link tracking and put it into a wrapper function to be executed in an onclick event (or add an event listener, etc..).
The first thing you want to do is decide what "events" you want to have for the widget(s). You mentioned counting "widget views". That's easy enough to do: just put a snippet of custom code on the page the widget is embedded on.
But beyond that...does clicking any button count as a single event? Does each button signify a different event? etc... Also, are there any custom values you want to associate with the buttons, like a product ID or description or whatever.
Another important thing to ask yourself when deciding on what you want to track is "How actionable is this data?" There is very little you can't track, but there are a lot of things that aren't very useful for making real business decisions.
For example, it sounds like overall you are wanting to try to measure user interaction with widgets. I'm sure the idea is to figure out how useful, engaging, etc... they are to people, so you can figure out whether it's worth further developing them or throwing money at them or dropping them. Fair enough. But just remember to make the events goal-oriented. Knowing how many times a user clicked a button isn't very useful because all by itself it isn't very actionable. Knowing how many times people completed a process or step, etc.. is more actionable.
Once you have made a list of what all you want to track and when, then you can start building your custom code.
With GA, there are 2 main ways to track events and metrics: through steps/goals, and through custom variables. The way you setup steps/goals with GA is to have GA match what the URL of the page is. For example, if you have a newsletter signup form, the form page might be signup.html and the confirmation page might be signup_confirmation.html. You would then setup a goal in the GA interface. The goal would match for signup_confirmation.html and you could have a step be to look for signup.html. Then you can see how many people viewed your form and completed it vs. abandoned it.
You can use this same tracking method with events, by pushing a virtual page view to GA.
Here is an article detailing how to push a virtual page view:
http://www.google.com/support/analytics/bin/answer.py?hl=en&answer=55521
But basically, whenever the event happens (like a view of the widget, click of a button, etc.. you would execute the following javascript:
pageTracker._trackPageview(’virtual url here’);
Main thing to note about this method is that you can organize/categorize/provide hierarchy to your data by passing delimited values. This will help you rollup data for different widgets/sites.
The 2nd way to record events is with custom variables. Making use of custom variables during events provides a lot of reporting possibilities and flexibility. Here is a link to how to use them:
http://code.google.com/apis/analytics/docs/tracking/gaTrackingCustomVariables.html
Related
So I have yet another DurandalJS question.
So I have a few widgets that are pretty much self contained. They render or hide themselves depending on whether the current user is logged in or not e.g. I have a widget that displays the current users name, and another one that displays some setting for the current user. The 'current user is a value stored in local storage so everyone basically knows to get it from there and do their bit.
I have a security module which triggers an event on itself when a user is logged in and when a user is logged out.
All my widgets including shell require this security module and they all handle the event.
Now I know the event is working because shell's event handler gets called but the widgets never see the event even thought they are displayed in shell.
However, if I do a hard refresh of the page (whether the user is logged in or out), all the widgets render properly so I know the widgets know what to do.
Am I doing this wrong? If yes how best do I go about it.
Thanks
The problem was that I was returning singletons from my widgets. I have no idea what the difference was but I never got the events when I returned singletons. Durandal expects widgets to be constructor functions so that it can instantiate multiple widgets of the same kind see here
viewmodel.js is a function exported module that will serve as a location for all your widget's code. It will be bound to view.html by the widget infrastructure via the composition module.
I'm building an AJAX 'web application' where, once the UI is loaded, calls to the server are for 'data exchange' only. As a result a lot of UI manipulation will be done using Javascript. Lets say the Javascript retrieves some data consisting of multiple fields from the server using AJAX. To put it on the screen I can think of multiple approaches -
Call methods like createElement() and appendChild() to build an interface to display the retrieved data
Populate the .innerHTML for the container element then for every data field lookup a container in the newly added HTML and populate it. The data that goes into .innerHTML could be stored in a JS variable or contained in a hidden node, or fetched using a seperate AJAX call.
Have the interface stored in a hidden node. Clone it (using cloneNode()) and put it in the actual container (using appendChild()) and then populate it with fields like in method 2.
and there are probably more ways.
Could you share pros, cons and possible gotachas in these approaches from cross-browser support, performance and coding complexity point of views?
Somewhat related question: Is client-side UI rendering via Javascript a good idea?
Thanks.
ok, let's start off:
Use toolkits
First you would want to invest time learning a JS toolkit. While others suggest native JS is good (which it really is), but you would not want to waste time on building apps that don't work cross-browser or spend too much time testing it. People in the community have invested their time in doing that for you. Show some love to the open community and use their product. I personally use jQuery, but there are others like Dojo and YUI.
But still use native JS whenever possible. It's still faster.
Structure your code
After a toolkit, you need some structure. BackboneJS will take care of that. It's to structure your code so that your code is reusable and well.. won't end up as spaghetti on your screen. Other tools like RequireJS are also useful for those scripts that need other scripts to run.
Templates: From strings to elements
Then, with that, you now have a toolkit but you still need to build the interface. It's better if you use a templating engine like Mustache or Handlebars. These render templates for your UI from strings (yes, plain strings of HTML). Just send over your template data from the server, store it in your app (in a variable or browser localstorage), and reuse it as necessary. No need for cloning hidden nodes!
Don't touch that DOM
As for approaching the DOM, you should touch the DOM only when necessary. DOM is slow, manipulating it is he** slow! that means you should avoid unnecessary animations, avoid excessive element append and remove, as well as changing styles. Check this article about avoiding too much reflow and repaints. Face it, the user won't event notice the round corners of your boxes, or the gradient background and don't even care if you did a slide animation or a fade-out. What they want is to get the job done and not adore the fireworks display.
Also, remove anything that isn't on screen. You might end up having 20% content on screen, and 80% off screen - a waste of memory.
Cache: fetch once, store, use infinitely for later
Now, your app is getting heavy and you want to shave off some HTTP requests. You can do this by caching. I usually use caching mostly on the templates so that every new UI, you don't need to load again from the server. You can do this by storing stuff in an object. you can go a little further and use the browser's localStorage when available.
Caching isn't all for the network. Let's say you have some complex calculations you want to use later, or some text from an unfinished form, use the cache for that too.
Avoid HTTP requests (or at least lighten them up)
While lightening up your app by using AJAX, you will inevitably be tempted to use AJAX just about anywhere - don't abuse it. Often times i see people who aggressively poll the server (every half-second or less). This not only strains the server (too many requests), but also the browser (wasting processing cycles) and the network (bandwidth). There are several practices done these days to avoid added HTTP requests:
Image Spriting - The art of placing a lot of images into one image and using background-position to change the image. Surely beats 100 individual HTTP requests
Use JSON for textual data - AJAX was meant to use XML.. then came along JSON that was a fat-free, platform-independent format of strucured data.
Do not return HTML-formatted data - With exemption of templates, which are HTML strings, you should never return HTML-formatted data over the wire. Have JS do JSON+templates on the client-side instead.
I'm building a similar app (Lightweight CMS)
In my view the approach you take will be dependent on the complexity of data that you are sending from the server > manipulating on the client side > and returning back to the server and db.
The cms that I'm working on is very basic and does not require heavy-duty manupulation on the client side. TinyMCE is as far as it will go.
Initially I was building the client admin area by echoing <input> from php and then collecting the data by parsing the DOM, converting to JSON and AJAX it back to the server (I found this code very helpful)
That of course required the user to hit "save" after editing or adding new data.
I later on decided that I needed something even more responsive and simpler than that so I'm now re-implementing everything for Jeditable which AJAXes the data as soon as the client hits "OK" on that particular field. No "main save" required.
To conclude it's really an area that is pretty uncharted. I mean, it appears to me that people in the industry do not like to blur that line between back-end and front-end and find "one solution" that will do the entire DB>SERVER>CLIENT>SERVER>DB operation.
I'd love to see how you solved your problem.
Just my 2 cents.
I want to track multiple events using GA _trackEvent method across multiple domains.
Because of the nature of the report I want to generate, I must do something like this:
for (var i=0; var < books.length; i++)
{
//showing values for current books[i]
_gaq.push(['_trackEvent', 'Books Displayed', 'Fantasy', 'Lord of The Rings']);
}
So, when my books list is populated I want to send appropriate GA event. It is important that I send each item separately so I can drill-down on Event Dashboard to preview all items in 'Fantasy' category and so on.
Note, books list is never longer than about 10 items.
The problem I'm experiencing at the moment is that for no good reason Google code is ignoring some of my requests. The way how Google event tracking works, is that with every call to _trackEvent, Google is dropping gif on the page:
http://www.google-analytics.com/__utm.gif
that has loads of parameters, and one of them - utme contains my data:
__utm.gif?utmt=event&utme=5(Books%20Displayed*Fantasy*Lord%20of%20The%20Rings)
Using Fiddler (or Firebug Net tab) I can check if this request is really coming out from the browser.
Unfortunately, it seems like every time about half of my requests are completely ignored by google and _trackEvent is not translated to __utm.gif call.
I have a feeling it has something to do with the frequency of the _trackEvent call. Because I am using them inside a for loop, all events are spawned with minimal interval between. It seems like Google doesn't like it, and ignores my calls.
I did test it, adding 2 seconds interval between each call and it worked. But this solution is unacceptable - I can't make user wait for 20 seconds to send all events.
Unfortunately this flaw makes GA Event Tracking completely useless - I can't just "hope" GA code will correctly record my event because the report won't be precise. The worst thing about it is that there is no proper documentation on Google saying what is the maximum allowed number of requests per second (they only state that max request per session is 500 what is a lot more than what I generate anyway).
My question is - did you experience similar problems with Google Event tracking before and how did you manage to fix it? Or does it mean I must completely abandon GA Tracking because it will never be precise enough?
First off, I want to point out that the 500 limit per session is for all requests to Google, not just for events. So that includes any other custom tracking you are doing, and that also includes normal page view hits.
This to me sounds more like a general js issue than a GA issue. Something along the lines of you pushing code for GA to process faster than it can process so some are falling through the cracks. I don't think there really is anything you can do about that except for delay each push as you have done...though I think you could probably lower that interval from 2s to maybe as low as 500ms...but still, that would at best drop you down to a 5 second wait, which IMO is a lot better than 20s but still too long.
One solution that might work would be for you to skip using _gaq.push() and output an image tag with the URL and params directly for each one. This is sort of the same principle as the "traditional" GA code that came before the async version, and is what most other analytics tools still do today.
If you want my honest opinion though...in my experience with web analytics, I think the most likely thing here is that you need to re-evaluate what you are tracking in the first place.
Judging by the context of your values, (and this is just a guess) it looks to me like you have for instance a page where a user can see a list of books, like a search results page or maybe a general "featured books" page or something similar, and you are wanting to track all the books a user sees on that page.
Based on my experience with web analytics, you are being way too granular about the data you collect. My advice to you is to sit down and ask yourself "How actionable is this data?" That is, after all, the point of web analytics - to help make actionable decisions.
All day long I see clients fall into the trap of wanting to know absolutely every minute detail about stuff because they think it will help them answer something or make some kind of decision, and 99% of the time, it doesn't. It is one thing to track as an event individual books a user views, like an individual product details page, where you'd be tracking a single event.
Or for search results page...track it as a "search" event, popping stuff like what the term searched was, how many results given, etc.. but not details about what was actually returned.
I guess if I knew more details about your site and what this tracking is for, I could maybe give you more solid advice :/
This is probably due to the 1 event per second limit
"Events Per Session Limit
In addition to general collection limits and quotas, the following limit applies to event tracking in ga.js:
The first 10 event hits sent to Google Analytics are tracked immediately, thereafter tracking is rate limited to one event hit per second.
As the number of events in a session approaches the collection limit, additional events might not be tracked. For this reason, you should:
avoid scripting a video to send an event for every second played and other highly repetitive event triggers
avoid excessive mouse movement tracking
avoid time-lapse mechanisms that generate high event counts
(from https://developers.google.com/analytics/devguides/collection/gajs/eventTrackerGuide)
That is why your 2 seconds delay works. You can theoretically cut that in half, though a factor of safety would probably reduce that cut.
I have some good experience with Google Analytics and have been using it for years. I've done some basic tracking and some event tracking from flash and AJAX apps. I'm working on a project now that has detail pages about people, but the query string is an ID rather than a SEO-friendly URL. (e.g. bio.aspx?id=3945 vs. /bios/ursino-mark.aspx). I have the actual info about the person (like name) in ASP.NET and I'd like to somehow pass it to Google Analytics so we know more about the actual page in the report, other than just a number. I've looked into this and found Custom Variables in GA. I'm wondering if there are any other options/recommendations?
Based on the information you give in the question, Custom Variables are indeed the method you'd want to proceed with. (There's also the possibility of using the 'User Defined Variables', but their use is discouraged, as the feature is considered deprecated in favor of Custom Variables.)
In contrast to Events, Custom Variables don't create their own request to Google Analytics; instead, they define an attribute of the hits (events, pageviews, transactions) that result from the given custom variable scope. Thus, they're the best way to send extra data about something you're already tracking (ie, pageviews.)
In that sense, the best usage for you would be to set a page-level custom variable before the _trackPageview call with the name of the person in question, always in the same slot. (Since each bio page would be their own page, setting it at the page-level scope would prevent any variable-overwriting issues, as there would never be any overlap.)
In this sense, you can think of a custom variable being something that describes the page/session/visitor, rather than describing a particular interaction (which is what Events are better suited for.)
To push custom variables and events to Google Analytics use this method.
_gaq.push(['_trackEvent',
'Shopping', // category of activity
'Item Removal', // Action
]);
You can learn more about tracking events from code.google.com:
http://code.google.com/apis/analytics/docs/tracking/gaTrackingCustomVariables.html
i would consider using virtual pages in the analytics. you can report all personal pages under the same virtual directory so that you will be able to easily filter out this data. something like /personal-pages/Mark-Ursino or /personal-pages/john-smith
I want to implement a 'live search' or 'search suggestions' feature in a web application that uses the Dojo Framework. It would be similar to the way Google and Bing searches display matches as you type: when you type in the search box, a list of potential matches appears below. Searches would be performed server side, with the results sent back to the browser using AJAX.
Does anyone know of a good way to implement this using Dojo?
Here are some potential options:
The built-in widget dijit.form.ComboBox
This has very similar functionality, but I've only seen it used with limited data sets. The examples always use small lists (such as the 50 states in USA) and preload the entire data set for client-side filtering. However I presume I could hook it up to a dojox.data.JsonQueryRestStore for server-side search — can anyone confirm whether that works?
QueryBox http://marumushi.com/code/querybox/
This implementation mainly does the job, but it has some minor bugs and doesn't look like it's being maintained. I'd have to do some bugfixes on the code before using it.
Medryx http://blog.medryx.org/2008/09/10/dijitsearch-part-2/
This also looks like it does the job, but it is described as 'alpha-level' code and the link to the code seems to be broken...
I could probably make one of the above work, but I'd like to know if there are any better alternatives out there.
I implemented it 5 years ago when Dojo was at 0.2:
http://www.lazutkin.com/blog/2005/12/23/live-filtering/
While the code is ancient, it is trivial, and hopefully it'll give you ideas on how to attack it. The rough sketch:
Attach an event handler to your input box, which is triggered on changes — use "onkeyup" to detect a change in the input box.
Wait until user stopped typing by setting a timer in your event handler, if it is not set yet. 200-500ms are good waiting times.
The timeout plays a dual role:
It throttles our requests to a server to prevent overloading.
It plays on our perception of time and our typing habits.
If our timeout is up, and we don't wait for a server ⇒ send server a string we have so far.
If we are still waiting for a server, cancel the request and ask again.
This part is app-specific: we don't want to overload a server, and sometimes a server cannot handle broken connections well.
In the example I don't cancel the XHR call, but wait it to finish first before submitting new request.
Server responds with relevant results, which are promptly shown.
In the blog post I implemented it as a widget. Obviously the exact packaging is up to you.