The Personal Blog of Bradon Kanyid

Using Songkick API in Javascript

2013-09-01

Songkick is a music service that finds local concerts based on your personal tastes. You give it some info about what you like, either through an exported iTunes library, Pandora playlist, or Last.fm scrobble history, tell it where you’re interested in going, and it lets you know who is playing and where. I’ve been a happy user for at least two years now, and it’s a really good tool for tracking tours and concert history.

Requesting an API Key

For all the aspects I enjoy about Songkick, I found it somewhat difficult directing people to my Upcoming Events calendar. They don’t seem to offer any pre-configured way to embed the content in other places, but they do offer an API now. I requested an API key, and went to work trying to embed my Upcoming Events calendar into this blog post.

Dynamic Content on a Static Site?

Initially, I thought I would do something similar to Mopidy-Subsonic and start working on some Python to decode the JSON I get from Songkick. However, I want to put it on this website, and my website is static content only. If I want any dynamic content, I’ll have to resort to client-side Javascript, similar to how Disqus works for my blog comments. I am no Javascript expert, especially for client-side content, and I am no DOM expert either. However, I saw in the documentation that the right kind of request would generate JSONP, which I could then assign to a callback to do all the parsing and generating work. I imagined that at that point, I could fill in something like an empty div tag on the page with the generated HTML. My initial research on how to generate the API call bore interesting fruit. It was difficult to find much in the way of doing this without a library. Everyone uses JQuery or Prototype for this, it seems. I like libraries, but I don’t want to add an entire library for one small feature, and I want to have an understanding of how it works before I rely on the library. I don’t like magic. I found an article on requesting remote JSON without JQuery on Stack Overflow, and modified it to support the JSONP callback convention. I later found an article on the differences between JSONP and JSON, which gave a similar snippet for attaching the JSONP as a script.

Javascript Code

I’ve made a few comments in the code below to give you an idea what’s going on, but the meat of the work is in the getConcertHTML function, a callback that is triggered when the JSONP object is received from Songkick. I’m using simple string concatenation to build up some generated HTML, which then replaces the content of the HTML element with ‘songkick’ as its ID.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// callback used to process the JSONP object
var genConcertHTML = function(json) {
var myHTML = ''

// iterate through the entries in the results
for (var entry = 0, entries = json.resultsPage.totalEntries; entry < entries; entry++) {
// grab the elements we are interested in
var event = json.resultsPage.results.calendarEntry[entry].event;
var reason = json.resultsPage.results.calendarEntry[entry].reason;
var date = event.start.date;
var venue = event.venue.displayName;
var uri = event.uri;
var status = reason.attendance == 'im_going' ? "I'm going" : "Maybe";

// put these elements into our generated HTML
myHTML += '<div class="page-header"><h3>'
myHTML += '<a href="' + uri + '">' + date + ' at ' + venue + '</a> - ' + status + '</h3>';

// further iterate through the artists at a concert and generate an unordered list
myHTML += '<ul>'
for (var perf = 0, perfs = event.performance.length; perf < perfs; perf++) {
var artist = event.performance[perf].artist;
var name = artist.displayName;
var band_uri = artist.uri;
myHTML += '<li><a href="' + band_uri + '">' + name + '</a></li>';
}
myHTML += '</ul></div>';
}
document.getElementById('songkick').innerHTML = myHTML;
}

// setup Songkick API call
var sk_base = "https://api.songkick.com/api/3.0/users/<user>/";
var sk_method = "calendar.json?reason=attendance";
var sk_apikey = "<apikey>";
var sk_callback = "&jsoncallback=genConcertHTML";
var sk_call = sk_base + sk_method + "&apikey=" + sk_apikey + sk_callback;

// create script element, point at API call, and attach to page
var script = document.createElement('script');
script.src = sk_call;
document.getElementsByTagName('head')[0].appendChild(script);

Static Site Code

For the static side, I’m using Misaki, a static site generator in Clojure. It has allowed me to use native Clojure code and a little glue to make this blog, using a simple templating format. As you can see below, you are still using what are basically tags in the Clojure code, but it abstracts away a lot of the templating, formatting and resource management. You can read more about making this blog, if you are interested. A paragraph tag is created with the id ‘songkick’, and the Javascript code above is loaded into it. This element is later replaced by the callback.

1
2
3
4
5
6
7
8
9
10
; @layout post
; @title Using Songkick API in Javascript
; @tag webdev music javascript

(defn songkick-content []
(p {:id "songkick"} (js "/js/post/songkick.js")))

...other content...

(songkick-content)

Conclusion

So, the Upcoming Events are shown below. The formatting isn’t great, but it is functional. I’m curious what it would take to pull some of the templating out of the HTML generation code of the callback, because right now I have to hard-code some things like the styles. Perhaps something like the jQuery or Protype library would be useful for this. In the future, I would like to make an IRC bot that you could query for the same information in a channel. It shouldn’t be hard to make a Python wrapper for the entire API, similar to libsonic, which I’m using in Mopidy-Subsonic. I hope you’ve enjoyed reading this post. I’m still catching up on a few posts that are backlogged, so hopefully there will be more soon.

Songkick Upcoming Events Calendar


Blog comments powered by Disqus