Making Google Analytics and jQuery Mobile Work Together

The jQuery Mobile framework is excellent for many things, but its single page architecture can be hard to track through analytics packages. This post will show you how to make some tweaks to your Google Analytics insert code to help it gather statistics from jQuery Mobile.

A little more background on why this is necessary… Within jQuery Mobile each page view is just a specific snippet of HTML on a single HTML page pulled into the browser view by Javascript. Most analytics packages treat these visits as a single page load and your page view statistics end up looking like, well, not much as the only page recorded is the source page – index.html. Not very helpful in terms of analysis… Google Analytics requires a few tweaks to be able to record these Javascript-generated page views. Here are the steps to make that happen.

Step 1: Include the asynchronous Google Analytics script loader between the <head> tags in your jQuery Mobile index page.

<script type="text/javascript">
 var _gaq = _gaq || [];
 _gaq.push(['_setAccount', 'UA-XXXXXXXX-XX']);
 _gaq.push(['_gat._anonymizeIp']);
(function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0];
  s.parentNode.insertBefore(ga, s);
 })();
</script>

All we have done here is bring the Google Analytics Javascript tracking code onto the page. You will need to specify the Google Profile Account ID you received when setting up your Google Analytics web property to identify the web site/app you want to track. (Add that info to the “UA-XXXXXXXX-XX” section above.) We included the asynchronous loader method as it lets other parts of the page load as connections become available and helps with performance over spotty mobile networks (or dodgy networks anywhere…).

Step 2: Using the jQuery base library script and its native functions, add a “track page views” event right before the closing of the <body> tag in your jQuery Mobile index page.

<script type="text/javascript">
 $('[data-role=page]').on('pageshow', function (event, ui) {
  try {
    _gaq.push( ['_trackPageview', event.target.id] );
    console.log(event.target.id);
  } catch(err) {
  }
});
</script>

In the routine above, we set up the “pageshow” event to make a note of any action on the page and we are binding that event to the Google Analytics _trackPageview() method on every page load to allow for a recording of any live action on the page. With the line – “_gaq.push( [‘_trackPageview’, event.target.id] );” – we are telling Google Analytics to record the specific page id in the HTML into our analytics data. With these changes, the logs start to look more familiar and each snippet of HTML that has been visited will be part of the log record.

screenshot showing Google Analytics after applying jQuery Mobile modifications

[Figure 1: Screenshot showing Google Analytics recording each page view in a jQuery Mobile app]

A final note: Under this method of tracking, the way you identify your individual pages within jQuery Mobile is important. Use markup and names that will make sense when you see them in your Google Analytics logs (or any logs for that matter…). Some sample markup:

<div data-role="page" id="search" data-theme="d">

Because the page id has been set up intuitively, I will be able to look for “search” in my Google Analytics reports and get specific tracking data about that particular “page”.

To see a full HTML example with all of the above code in context, visit http://www.lib.montana.edu/~jason/files/touch-jquery/ and “view source”.


Getting vCard info into a QR code using the Google Chart API

How to get vCard info into a QR code using the Google Chart API? This question has been coming up occasionally and it can be a little quirky. I thought I might document my process of making this work with the Google Chart API.

1. Create the unencoded vCard info. Sample Below:

BEGIN:VCARD VERSION:3.0
N:Clark;Jason
FN:Jason Clark
ORG:MSU Library
TITLE:Team Leader/Digital Initiatives Librarian [Associate Professor]
TEL;TYPE=WORK,VOICE:(406) 994-6801
EMAIL;TYPE=PREF,INTERNET:jaclark@montana.edu
URL:http://www.jasonclark.info
REV:20111013T195243Z
END:VCARD

2. Run the unencoded vCard info through a utility or programming function. In this example, we are using the online “URI Encoder / Decoder” tool http://andrewu.co.uk/tools/uriencoder/. Some common functions in programming languages that would do the same thing are: Server.URLEncode() in ASP, urlencode() in PHP, and encodeURI() in Javascript. After pushing the unencoded vCard string through the “URI Encoder / Decoder” tool, we get a resulting string like this:

BEGIN%3AVCARD%0D%0A%09%09
VERSION%3A3.0%0D%0A%09%09N%3AClark%3BJason%0D%0A%09%09
FN%3AJason+Clark%0D%0A%09%09ORG%3AMSU+Library%0D%0A%09%09
TITurLE%3ATeam+Leader%2FDigital+Initiatives+Librarian+%5BAssociate+Professor%5D%0D%0A%09%09
TEL%3BTYPE%3DWORK%2CVOICE%3A%28406%29+994-6801%0D%0A%09%09EMAIL%3BTYPE%3DPREF%2CINTERNET%3Ajaclark%40montana.edu%0D%0A%09%09
URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09
REV%3A20111013T195243Z%0D%0A%09%09
END%3AVCARD

A potential gotcha here is the URL value in the vCard. Make sure the URL value in the vCard is encoded and has changed from

URL:http://www.jasonclark.info

to something that looks like:

URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09

3. Next, we place the encoded string in the Google Chart API to generate the QR code. Put your encoded vCard string in the URL below after the “&chl=”. For more info, see the online wizard tool and documentation for the Google Chart API. Check the link below to see the generated QR code.

http://chart.apis.google.com/chart?chs=200x200&cht=qr&chld=|0&chl=BEGIN%3AVCARD%0D%0A%09%09VERSION%3A3.0%0D%0A%09%09N%3AClark%3BJason%0D%0A%09%09FN%3AJason+Clark%0D%0A%09%09ORG%3AMSU+Library%0D%0A%09%09TITLE%3ATeam+Leader%2FDigital+Initiatives+Librarian+%5BAssociate+Professor%5D%0D%0A%09%09TEL%3BTYPE%3DWORK%2CVOICE%3A%28406%29+994-6801%0D%0A%09%09EMAIL%3BTYPE%3DPREF%2CINTERNET%3Ajaclark%40montana.edu%0D%0A%09%09URL%3Ahttp%3A%2F%2Fwww.jasonclark.info%0D%0A%09%09REV%3A20111013T195243Z%0D%0A%09%09END%3AVCARD

4. If everything works, the Google Chart API returns a link to a QR code image with the vCard info encoded. Place this URL in an HTML <img> tag and you’ll have a QR code on your site that will have vCard data. Note: You will need to add your specific contact vCard data in Step 1.


Mapping your location with Google Static Maps API (tutorial)

The Google Static Maps API  (code.google.com/apis/maps/documentation/staticmaps/) allows for a dead simple way to embed maps showing a specific location for mobile and desktop environments. The real advantage of the Google Static Maps API is that the embed comes in the form of an HTML image <img> tag. In this quick codelab tutorial, I’m going to show you how to create a static map and set a location using the Google Static Maps API. If you have a familiarity with HTML, the markup for the image should be familiar.

<img src=”http://maps.google.com/maps/api/staticmap?center=Bozeman,MT&zoom=13&size=310×310&markers=color:blue|45.666671,-111.04859&mobile=true&sensor=false” />

As I mentioned earlier, it is a simple <img> tag with a call linking into the Google Static Maps API. In order to assign a specific location we need to pass a few parameters to the Google Static Maps API. Included among the customizations:

  1. A central location for the map
  2. A zoom level for the map
  3. A size for our map image
  4. A marker color and position using latitude and longitude
  5. Set the map to display for mobile settings without a sensor

The necessary pieces to enter are a central location and your specific latitude and longitude. Enter your hometown for the central location in the format of {city, state or principality}. To get your latitude and longitude, visit gmaps-samples-v3.googlecode.com/svn/trunk/geocoder/getlatlng.html and type in your library address. Copy the latitude and longitude values that are returned. Enter these position values as a comma separated string {latitude,longitude}.

Here’s the image src= markup with cues for where to add your values.

http://maps.google.com/maps/api/staticmap?center={YOURHOMETOWN}&zoom=13&size=310×310&markers=color:blue|{YOUR LATITUDE/LONGITUDE}&mobile=true&sensor=false

Once you have the link filled out add it to your image <img> tag on a live HTML page and you will have a local map to your library or any other specific location.

msu library bozeman mt


Librarian Day in the Life, Day 5 (Round 4)

The fifth day in the life of the Head of Digital Access and Web Services at Montana State University Libraries. Based on tweets in chronological order.

  • 8:35am. AM check of email & twitter. My annual review is today at 2:30pm. Should be a good conversation with the deans. #libday4
  • 9:15am. Filling out monthly summary leave reports. Have a block of time before annual review. Need to stay in office & close door. #libday4
  • 10:58am. Email faculty re: feedback on tenure document revisions due noon on Mon. Reading draft of 3-5 year strategic plan for lib. #libday4
  • 11:09am. Quick visit w/team member re: moving architectural drawings app into production. Performing code audit and moving it up. #libday4
  • 1pm. Heading to lunch. Answered a quick Infotoday #cil2010 email re: javascript workshop. http://bit.ly/bLQEf5 #libday4
  • 2:17pm. Excited by opps for DAWS team in strategic plan. Digitization, archiving, web services… Heading to annual review. #libday4
  • 3:30pm. Good review. Now meeting w/range science faculty re: U of Idaho participation in MSU range science DB. http://bit.ly/9nneBb #libday4
  • 4:50pm. Joy 2 meet faculty that geeks out over pictures of grass you digitized. Collab w/U of Idaho looks promising. Weekend. End #libday4.

Ahh, the fifth and final installment… LibraryWeekintheLife… It was a Friday which is usually an open day for me. Time to think about week, start on some projects, prepare for next week. It also a day where some admin duties get finished. The morning was mostly about taking advantage of some free time to talk to team members, audit some code before making it live, and preparing for my annual review. The review was a good conversation about where my work is heading and how the team can help the library in the next year. Nice surprise at the end of the day as a range science professor was giddy to see some of the Hormay collection digital objects. It always helps to see someone genuinely excited about your work. There are times when you wonder who’s going to find this stuff valuable. More people do than you know… It also looks like there may be some funding for the range science project. Great to see as we did the initial metadata, DB and app design, and conversion pro bono. The theory was: if we show them something of value, we would be able to look for funding with next iteration. Worked out this time.


Librarian Day in the Life, Day 4 (Round 4)

The fourth day in the life of the Head of Digital Access and Web Services at Montana State University Libraries. Based on tweets in chronological order.
  • 8:35am. AM check of “the twitter” & email. Corresponding with film grad student over plans to do promo for Digital team. Start #libday4.
  • 9:45am. Thinking re: how to present Herbarium project to Bio Faculty. Working w/team on collaborative indexing/keyword project. #libday4
  • 12:35pm. Big win @ meeting w/faculty re: Herbarium. All metadata & scanning will be done by motivated faculty member. Lunchtime. #libday4
  • 3pm. Drop ins & drop bys. Conversation w/team & colleagues re: new digital media service. How to launch, get buy-in, make it easy. #libday4
  • 3:10pm. Filling out student time cards and reporting team leave for admin. Living the dream. #libday4
  • 3:21pm. Hour or so in front of me. Time to work on topic recommending search engine (proof of concept). Work includes data entry. #libday4
  • 4:17pm. Making Libguides API play nice with our database lists. I hate you unencoded &, but you are now fixed with urlencode(). #libday4
  • 4:33pm. @springshare @LibGuidesFAQ Whom do I talk to about structured data coming out of your API? <LI> in caps is not valid HTML. #libday4
  • 4:40pm. Broke search app. Checking error logs. Good place to stop for now. PM email check and then home to fam. Fix later. #libday4
  • 4:46pm. tail -50 error_log command gives: “syntax error, unexpected ‘ on line 253 of view.php” Note for later. #libday4
  • 8:57pm. Back in the saddle. Email colleague in Arts & Architecture re: people we met yesterday interested in go2collegeMT.org. #libday4
  • 9:05pm. Tracking down parse error in “search for databases by topic” app. #libday4
  • 10:05pm. Reducing noise to signal ratio in Google reader. Best signals get bookmarked at delicious/diginit/ #libday4
  • 10:35pm. Final PM email check. Thread re: Bio faculty’s flickr photostream @ http://bit.ly/aQeMVB ; metadata for plant repositories. #libday4
  • 10:55pm. Falling asleep at the wheel. Will have to fix search tomorrow. End #libday4.

Pretty average day.  Had some nice chunks of time, but I chose to do the face to face thing a little more.  It can take more time, but the “Drop Bys” can be an effective means of getting a person’s true feelings on a subject. No mediation by email or other tech, just one on one conversation. You can see some of my admin duties above as it’s the end of the month. Necessary stuff, but not my favorite. Big news for the day was the meeting with a Plant Sciences faculty about digitization of Montana herbarium samples. He’s already using flickr and has access to a high res camera. To top it off, he’s motivated to do metadata. Huge. Subject specialist with integral knowledge of objects doing first batch of metadata. We have plans to go after grant, but will build prototype using flickr API. Tasks for the day included: programming, data entry, networking, negotiating org politics, debugging, “metadataing”, admin documentation, prototyping, and sleeping. More tomorrow as I have my annual review with my deans… Bring it.


Librarian Day in the Life, Day 3 (round 4)

The third day in the life of the Head of Digital Access and Web Services at Montana State University Libraries. Based on tweets in chronological order.
  • 7:30am. Has decided that Earl Grey Tea doesn’t cut it. Going for coffee. Start #libday4.
  • 8:25am. AM email check. Thread re: ALA talk on cloud computing. Building search index for article DBs w/keywords fm Yahoo BOSS API. #libday4
  • 9:42am. Figuring out how MySQL automagically does relevance ranking. http://bit.ly/16tf6R #libday4
  • 9:52am. Checking MySQL error logs. #libday4
  • 10am. MSU herbarium digital project discussion. #libday4
  • 11am. Preso to school counselors re: go2collegeMT.org. #libday4
  • 12:41pm Back fm lunch. 11am pres to MT school counselors on new tech in education went well. Open afternoon. Time for programming. #libday4
  • 2:15pm Still working on optimizing search index for articles. Making progress with mysteries of MySQL relevancy ranking. #libday4
  • 4:15pm. Search interface is on dev. Team testing queries. PM email check. This portion of day over. Time for Fam time. More later. #libday4
  • 9:15pm. Back again. Trying to make openURL queries to Serial Solutions API work from one of our citation DBs http://bit.ly/9nneBb . #libday4
  • 10:15pm. Trolling through my feeds via Google Reader. Saving/tagging interesting stuff to Delicious. #libday4
  • 11:30pm. Google Waved reminder re: starting to record DOI in citation database records. It makes openURL much easier. End #libday4 day 3.

Quite a bit on the technical side today. Largely due to my having a 4 hour block in the afternoon. But, here’s the thing: if I want to build/work to customize library apps, I need these blocks of time. Picking away at these projects for a half hour here or there doesn’t work. Just before lunch, I had the opportunity to speak (with Terry Beaubois) to a group of school liaisions for the k-12 set. It was a Q & A session about new technologies that could be used in the classroom. uStream, iTunes for k-12, mobile devices were pieces of the discussion. It hardly gets any play above, but the MSU Herbarium project could be a winner. Rene Tanner has been working with the Bio department and pointing to our digitization services. Rene and I have an eye on some grant possibilities for the project and some early prototyping using Flickr as a data store.  Great day overall. Some of the meetings tomorrow have been canceled. I should have some big chunks of time tomorrow as well. Looking forward to it.


Librarian Day in the Life, Day 2 (round 4)

The second day in the life of the Head of Digital Access and Web Services at Montana State University Libraries. Based on tweets in chronological order.

9am team meeting. 10am MSU Extension Pub digitization meeting. Doing AM check on email. #libday4

11am Mtng w/instruction librarian to talk design & dev of mediaHub: http://bit.ly/cT8XQK . 11:30am weekly mtng w/Associate Dean. #libday4

12:37pm. Back fm lunch. Building interface for mentor/liaison app. Prepping for later mtng with colleague re: Openurl pres in Feb. #libday4

1:40pm. Google Waved initial questions for RangeLands West digital project. Looked at sample data for gotchas with data import. #libday4

2:35pm. Back from openURL presentation prep. Checking code demos: http://bit.ly/UKYEF . Need demos for general API mashup topic. #libday4

2:41pm. Coffee break with team member. #libday4

3:45pm. Back fm Library Faculty Advisory committee. Elected new chair & set up mtngs to facilitate discussion btwn Deans & Faculty #libday4

4:04pm. PM email check. Checked Google docs for shared presentation. Making sure files on dev server for work later after FAM time. #lib4day

4:35pm Going home to the fam. Colleague stopped by to ask about best format for data import. Loaded ? .csv in spreadsheet? #libday4

9:02pm. Baby sleeps. Working on Google maps mashup for ed grant. Maps colleges + events in MT. http://bit.ly/b0ENcr #libday4

10:15pm. Final email check. Finished with grant work. Time to relax. End #libday4.

This was a day with most of my meetings for the week. I’ve been trying to work my schedule this way as it frees up those precious blocks of time later in the week. Blocks of time where I can actually get some programming projects started. I’m still trying to find the work/life balance and you can see my working from home after Piper is in bed. This is very routine. If anything, I was surprised at how much I was able to work between meetings. That doesn’t always happen.


Librarian Day in the Life, Day 1 (round 4)

I decided this morning to participate in the “Librarian Day in the Life” project organized by Bobbi Newman. I like the idea of making my job more visible. I’m also hoping to learn about my typical week by capturing it in writing. I’ll primarily be tweeting the events at the hashtag #libday4 from my twitter account at twitter.com/jaclark. At the end of each day, I’ll present a digest of my tweets as a blog post with commentary if necessary. Here’s day 1:

Alright, I’m calling it. #libday4 day 1 is over. Tomorrow is my meeting day. Like to get that over early in the week.
less than 20 seconds ago from web
After baby hiatus… Drafting revision to tenure documentation. Auditing digitization opps with Range Science and MSU Herbarium. #libday4
13 minutes ago from web
Working on annual strategic initiatives for team. Prepping for team meeting tomorrow where we discuss possible initiatives. #libday4
about 7 hours ago from web
Rewriting some PHP and HTML code for web form/DB integration. Importing sample data into said DB. #libday4
about 8 hours ago from web
Writing about possible learning outcomes for ACRL webinar; Finalizing plans for #cil2010; Answering work emails. #libday4
about 10 hours ago from web
Working on geolocation javascript for project. Debugging w/help of Tweeps & FB. Release code sample and explain in blog post later. #libday4
about 11 hours ago from web
Help me test javascript geolocation function @ http://bit.ly/5U8mva . 1. Working accurately? 2. What browser? #libday4
about 12 hours ago from web
Mmm coffee… checking twitter, Google Reader for development, digitization, library stuff. My morning routine as human aggregator. #libday4
about 12 hours ago from web
@BillDrew4 My apologies for bumping you from #libday4 editing. I hit the wrong button.
about 13 hours ago from web
Down with the #libday4 mix.
about 13 hours ago from web

This day is a unique in that Monday is my “work off-site” day. As faculty, we have some freedom in how/when we get things done. As long as we are producing results, we have some latitude. It’s nice to work in a place that inherently trusts you. Monday is typically a research day, but this one turned into a social networking, coding, and documentation kind of day. Tuesday is my “day of meetings” as I like to get the face to face done early in the week and set up my projects. Expect some reporting on comings and goings tomorrow.


Mobile Web Design – Working Code, Tips, Best Practices

Taking a web site to the small screen comes with a host of considerations: device width, available bandwidth, touch versus click interfaces, browsers with limited functionality, etc. At the same time, the simplicity of these mobile browsing environments lowers the barrier to entry for developers. Some basic HTML and CSS is all that is required to get started. In my research, I have learned a few things and decided to put the learning into action by creating a mobile web template available for anyone to download, remix, and reuse.

Demo: http://www.lib.montana.edu/~jason/files/m/
Download: http://www.lib.montana.edu/~jason/files/m.zip
Read Me: http://www.lib.montana.edu/~jason/files/m/_readme.txt

The above template is using HTML, CSS, Javascript, and PHP, but you could substitute any server side language for the programming logic. I also have it in my head that I can build an even simpler template with just HTML and CSS. I’ll keep people updated…

Here are some tips, best practices, and design conventions I learned along the way.

  • One column is a design convention worth following (See m.facebook.com, or m.youtube.com, or m.twitter.com).
  • Pick the essence or core pieces of your site to deliver to your mobile users. Think abridged version.
  • Follow the “m” URL conventions (m.delicious.com OR amazon.mobi OR lifeonterra.com/m/).
  • Minify and optimize your CSS (See Clean CSS ).
  • Minify and optimize your javascript (see JSLint).
  • Plan for low bandwidth – Keep images close to 1KB or under.
  • Test on multiple mobile browsers and emulators.
  • Don’t plan on javascript being available – the above template still works when it’s turned off.
  • Build your app so that it loads only necessary data when requested (Use Ajax or Server-Side includes).

I’m interested in any feedback or questions so please share in the comments. I’ve also created a more robust mobile application example for TERRA: The Nature of Our World available at lifeonterra.com/m/. If anyone is interested, I’m happy to share some of that code as well.


Wordle View of Internet Librarian 2009

I like me some Wordle. For quick visualizations of trends in text, it can provide a quick snapshot. I’m heading home tomorrow as the Internet Librarian conference winds down, but I wanted to see what trends might appear if the Internet Librarian 2009 conference program was given the Wordle treatment. The result is below with stop words and some noise removed (e.g., library, libraries, time notations, conference track numbers, etc.).

Wordle: #il2009

Some of my quick observations: Google and books appear at about the same size. Mobile looks like it’s gaining some ground. Twitter makes an appearance. What else does this word cloud communicate about the tech side of the profession? Click on the thumbnail to get the full view.