Customizing the Display of Google Calendar Feeds

by Hans DeBano

  1. Google Calendar "Views"
  2. What Degree of Customization do I Need for Displaying Calendar Data?
  3. The Google AJAX Feed API
    1. An API Example: Displaying ASU's Student Academic Calendar in a Web Page
    2. API Example: Prerequisites
    3. API Example: HTML and JavaScript
    4. API Example: Notes
  4. Server vs. Client-side Approaches to Displaying Feeds

Google Calendar "Views"

As part of the Arizona State University (ASU) partnership with Google, students, faculty and staff all have access to Google Calendar.  Many ASU Google users also have separate, outside-ASU Google accounts with access to calendaring functionality.

One extremely useful feature of Google Calendar is the ability to expose a calendar publicly, to share with friends, family, clubs, etc. When a calendar has been shared with everybody, there are several "views" of it that Google automatically makes available. These different views of a public calendar include:

  1. an embedded (HTML) view of the calendar that can be displayed in a web page
  2. an iCal format of the calendar
  3. an Atom (XML) feed of the calendar

In addition, it's also possible to use one of many available calendar Google Gadgets to display a calendar gadget on a web page.

This article will focus on view #3: the feed and how this can be customized to display calendar events on a web page. This approach, rendering an Atom/RSS feed on a web page, isn't limited to calendar events—the general strategy can also be employed to display any RSS or Atom feed, such as one of an almost unlimited number of news feeds, on a web page.

What Degree of Customization do I Need for Displaying Calendar Data?

Many people will find that they're satisfied with the out-of-the-box display of Calendar data using embedded calendar HTML or inserting an appropriate calendar Google Gadget on the page.

There are special circumstances, however, where it's important to have more customization over how the event data is displayed on a web page. For this purpose, the Google AJAX Feed API, described next, allows a high degree of customization in how feed data is ordered and displayed on the page. It also provides you with extensive control over the HTML markup wrapping the calendar data.

The Google AJAX Feed API

The Google Ajax Feed API allows you to download public RSS or Atom feeds using only JavaScript. The feed formats supported are:

The Developer's Guide for this API is available at: http://code.google.com/apis/ajaxfeeds/documentation/ .

To get started using the API, you'll need to obtain an API key. To do this, you'll need a Google account, and once you've accepted Google's API Terms of Use, Google will display your new key on a web page. Then you'll be able to copy it from the web page and store it for future reference, as well as start using it in pages on your site.

The key applies to any directory (and its subdirectories) on your web site. You can create multiple API keys if you have multiple web sites.

The API documentation presents multiple code examples of using the Feed API.

Although the API has functionality for working with collections of feeds and discovering feeds, the instructions here will only relate to displaying a single feed on a web page.

An API Example: Displaying ASU's Student Academic Calendar in a Web Page

Suppose that you want to display the next five upcoming events from ASU's Student Academic Calendar in a maroon box on your web page like this:

Rendered Student Academic Calendar Feed

To fine-tune the fonts, spacing and colors used in the box, you'll want to use CSS. Furthermore, let's say that because you're picky about the HTML used to display the feed, you'll want the HTML markup for your div (the box) to use an unordered list and a "when" class on the event dates in each list item like this:

<div id="feed">
  <h2>ASU Student Academic Calendar Events</h2>
  <ul>
    <li><a href="http://www.google.com/calendar/hosted/asu.edu/event?eid=...">Fall 2007 Early Academic Status Report #2</a> <span class="when">(10/24/2007)</span></li>
    <li><a href="http://www.google.com/calendar/hosted/asu.edu/event?eid=...">Fall 2007 Course Withdrawal Deadline - In-Person</a> <span class="when">(11/2/2007)</span></li>
    <li><a href="http://www.google.com/calendar/hosted/asu.edu/event?eid=...">Fall 2007 Course Withdrawal Deadline - Online</a> <span class="when">(11/2/2007)</span></li>
    <li><a href="http://www.google.com/calendar/hosted/asu.edu/event?eid=...">Spring 2008 Enrollment Appointments Begin (Registration & Drop/Add for students with Enrollment Appointments)</a> <span class="when">(11/2/2007)</span></li>
    <li><a href="http://www.google.com/calendar/hosted/asu.edu/event?eid=...">Spring 2008 Registration & Tuition Guide Available - Online</a> <span class="when">(11/2/2007)</span></li>
  </ul>
</div>

API Example: Prerequisites

To get started, you'll need the following:

  1. your Feed API key
  2. the Google feed address (URL) of your calendar
  3. CSS for formatting your feed div
  4. the Atom elements containing your calendar data
  5. JavaScript utility for parsing dates
1. your Feed API key
This is the Google Ajax Feed API key that you obtained earlier. This is described above in "The Google AJAX Feed API."
2. the Google feed address (URL) of your calendar

Google's instructions describe how to get the public feed address, the "calendar address", of your calendar. (You'll be clicking on an "XML" button in the "Calendar Details" screen.) Note that ASU calendars will have a URL with a prefix like this: http://www.google.com/calendar/feeds/asu.edu...

It's important to note that various parameters can be added to the Google calendar feed address to customize the number, order and detail of events that it returns. The example JavaScript below uses the feed parameters: "orderby", "sortorder", "futureevents" and "max-results".

Equally important are the set of "projection names" that can be specified for a Google calendar feed. If you click on the XML button in "Calendar Details", the feed URL that you'll see is for the "basic" projection name. (You'll see "basic" as part of the URL.) You can replace "basic" with "full" or another projection name, as illustrated in the feed address used in the sample below.

3. CSS for formatting your feed div
You can use either external or inline CSS to control the appearance of your feed div. The styles might look something like this:
#feed {
  background: #903;
  border-top: 2px solid #eee;
  border-right: 2px solid #eee;
  color: #eee;
}

#feed a {
  color: #eee;
  text-decoration: none;
}

#feed a:hover {
  color: #ffb310;
  text-decoration: underline;
}

#feed h2 {
  margin: 16px 0 10px 20px;
  padding-right: 10px;
  font-size: 1.5em;
  font-weight: normal;
  color: #bababa;
}

#feed ul {
  margin: 0;
  padding: 10px 0 10px 0;
}

#feed ul li {
  list-style: none;
  margin-left: 0;
  padding-right: 15px;
  padding-left: 20px;
  font-size: 0.95em;
  line-height: 130%;
  color: #eee;
}

li span.when {
  color: #bababa;
}
4. the Atom elements containing your calendar data

The Google Data API specifies a namespace of allowed elements appearing in the calendar feed (and actually in more general contexts). If you use a projection value of "full", the feed XML will contain an extensive set of elements, one of which is "when". For example, the "when" element might appear in the Student Academic Calendar feed XML as: <gd:when startTime="2007-11-04" endTime="2007-11-05"/>. This element provides information about the starting and ending date (or datetime) of your event.

Your JavaScript can parse any of these Google elements present in the XML, depending on the level of customization desired.

5. JavaScript utility for parsing dates
The date and datetime values appearing in the Google "when" elements conform to a W3C subset of the ISO 8601 standards. Your JavaScript will need to parse this format if you'd like to manipulate those values. Fortunately, there is at least one example of this type of JavaScript parsing for your consumption.

API Example: HTML and JavaScript

The following HTML document with JavaScript produces the Student Academic Calendar box described above. Important portions of the code have been highlighted in yellow and described in notes below the example.

  1.  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  2.  <html xmlns="http://www.w3.org/1999/xhtml">
  3.    <head>
  4.      <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
  5.      <title>Google AJAX Feed API - Simple Example Using the ASU Student Academic Calendar</title>
  6.      <script type="text/javascript" src="http://www.google.com/jsapi?key={GOOGLEAPIKEYHERE}"></script>
  7.      <script type="text/javascript" src="javascript/iso8601dateparse.js"></script>
  8.     <script type="text/javascript">
  9.      google.load("feeds", "1");
  10.      function initialize() {
  11.        var feed = new       google.feeds.Feed("http://www.google.com/calendar/feeds/asu.edu_q065bkoducouhbr42c83548dgk%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&max-results=500");
  12.        feed.setResultFormat(google.feeds.Feed.XML_FORMAT);
  13.        // Default value displays only four feed entries
  14.        feed.setNumEntries(5);
  15.        feed.load(function(result) {
  16.        var container = document.getElementById("feed");
  17.        if (!result.error) {
  18.          var whenstring = '';
  19.          var entries = google.feeds.getElementsByTagNameNS(result.xmlDocument, "http://www.w3.org/2005/Atom", "entry");
  20.          var ul = document.createElement("ul");
  21.          for (var i = 0; i < entries.length; i++) {
  22.            var titleElement = google.feeds.getElementsByTagNameNS(entries[i], "http://www.w3.org/2005/Atom", "title")[0];
  23.            var title = titleElement.firstChild.nodeValue;
  24.            var mylinkElement = google.feeds.getElementsByTagNameNS(entries[i], "http://www.w3.org/2005/Atom", "link")[0];
  25.            var mylink = mylinkElement.getAttribute('href');
  26.            // change the link for adding the calendar to make it so that it adds to the user's ASU domain calendar
  27.            var newlink = mylink.replace("calendar/event", "calendar/hosted/asu.edu/event");
  28.            var whenElement = google.feeds.getElementsByTagNameNS(entries[i], "http://schemas.google.com/g/2005", "when")[0];
  29.            var starttime = whenElement.getAttribute('startTime');
  30.            var endtime = whenElement.getAttribute('endTime');
  31.            var startdate = new Date();
  32.            startdate.setISO8601(starttime, "-0700" );
  33.            var enddate = new Date();
  34.            enddate.setISO8601(starttime, "-0700" );
  35.            var startstring = (startdate.getMonth() + 1) + '/' + (startdate.getDate() + 1) + '/' + startdate.getFullYear();
  36.            var endstring = (enddate.getMonth() + 1) + '/' + (enddate.getDate() + 1) + '/' + enddate.getFullYear();
  37.            if (startstring == endstring) {
  38.              whenstring = '(' + startstring + ')';
  39.            }
  40.            else {
  41.              whenstring = '(' + 'starting: ' + startstring + ' ' + 'ending: ' + endstring + ')';
  42.            }
  43.            //embed the event date in a span element with class="when"
  44.            var spanwhen = document.createElement("span");
  45.            spanwhen.setAttribute("class", "when");
  46.            spanwhen.appendChild(document.createTextNode(whenstring));
  47.            //each feed entry is embedded in an HTML li element
  48.            var li = document.createElement("li");
  49.            var a = document.createElement("a");
  50.            a.setAttribute("href", newlink);
  51.            a.appendChild(document.createTextNode(title + ' '));
  52.            li.appendChild(a);
  53.            li.appendChild(spanwhen);
  54.            ul.appendChild(li);
  55.            }
  56.         container.appendChild(ul);
  57.         }
  58.      });
  59.      }
  60.      google.setOnLoadCallback(initialize);
  61.      </script>
  62.      <link rel="stylesheet" href="css/calendarfeed.css" type="text/css" />
  63.    </head>
  64.    <body>
  65.      <div id="feed">
  66.         <h2>ASU Student Academic Calendar Events</h2>
  67.     </div>
  68.    </body>
  69.  </html>

API Example: Notes

The following notes pertain to the HTML and JavaScript in the example above. This code has been highlighted in yellow to make it easier to see.

Server vs. Client-side Approaches to Displaying Feeds

The Google AJAX Feed API is entirely client-based and relies on JavaScript. If the user has turned off JavaScript, she won't see the feed data displayed in the page. In addition, the JavaScript dynamically changes elements in the document which means that most search engines won't index any content appearing in the feed box. In most cases this won't be a problem.

Some server-side technologies for displaying feed content can download the feed entries, then render them in the HTML of the page before sending it to the browser. This is different than dynamically modifying the DOM.