Almost a year ago I blogged about using the EventBrite API with ColdFusion. At that time, I was under the impression that all uses of the EventBrite API required a private OAuth token. This means it would not be possible to use the data on the client-side. (Unless you used a server to proxy the API calls for you of course.) But after speaking to Mitch Colleran from EventBrite, I was happy to discover I was wrong.

Turns out, when you create an app on the EventBrite developer portal, you actually get both a regular OAuth token and secret as well as an anonymous oauth token:

shot1

By using the anonymous oath token, you can read any public data you want, all without having to use a secure key. This means you can use the EventBrite API in a JavaScript app (desktop, mobile, hybrid, etc.) without worrying about keeping your key secret. In fact, their API is so easy to use you can actually pass in the anon key right in the URL.

As an example, given that token represents your anon oath token, this will get all public events:

https://www.eventbriteapi.com/v3/events/search/?token='+token

Obviously you probably want your own events, not the entire worlds. While it is trivial to restrict the results to your own organization, oddly it is still a bit awkward to get your organizer id. As I said in the old post, go to your profile and then your organization settings. You'll see your organizer URL with the ID at the end:

You can then pass it to the URL:

https://www.eventbriteapi.com/v3/events/search/?token='+token+'&organizer.id=8231868522&expand=venue'

In case you're curious, the expand=venue option there just tells the API to return venue information. Without it, you get the ID of the venue and could do more HTTP calls to get it, but returning it all at once is simpler.

Ok, so why bother? EventBrite already has embed options, right? Well they do - and those are nice - but if you want more control over the embed experience then you'll want the ability to write out the data as you see fit.

Here's an incredibly simple example that fetches events and displays them in a list.

<html>
<head>
	<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
	<script>
	$(document).ready(function() {
		
		var token = 'GGAQ2BUKIRGJMZMU55YZ';
		var $events = $("#events");
		
		$.get('https://www.eventbriteapi.com/v3/events/search/?token='+token+'&organizer.id=8231868522&expand=venue', function(res) {
			if(res.events.length) {
				var s = "<ul class='eventList'>";
				for(var i=0;i<res.events.length;i++) {
					var event = res.events[i];
					console.dir(event);
					s += "<li><a href='" + event.url + "'>" + event.name.text + "</a> - " + event.description.text + "</li>";
				}
				s += "</ul>";
				$events.html(s);
			} else {
				$events.html("<p>Sorry, there are no upcoming events.</p>");
			}
		});
		
		
	});
	</script>
</head>
<body>
	
<h2>Upcoming Events!</h2>
<div id="events"></div>
</body>
</html>

As I said, this is simple, so simple I assume it just makes sense, but if not, let me know in the comments below. After building this for an organization, I then worked on making it a bit nicer. For example, I formatted the Date using Moment.js:

<html>
<head>
	<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.3/moment.js"></script>
	<script>
	$(document).ready(function() {
		
		//anon oauth token
		var token = 'GGAQ2BUKIRGJMZMU55YZ';
		//org id
		var organizer = '8231868522';

		var $events = $("#events");
		
		$events.html("<i>Loading events, please stand by...</i>");
		$.get('https://www.eventbriteapi.com/v3/events/search/?token='+token+'&organizer.id='+organizer+'&expand=venue', function(res) {
			if(res.events.length) {
				var s = "";
				for(var i=0;i<res.events.length;i++) {
					var event = res.events[i];
					var eventTime = moment(event.start.local).format('M/D/YYYY h:mm A');
					console.dir(event);
					s += "<div class='eventList'>";
					s += "<h2><a href='" + event.url + "'>" + event.name.text + "</a></h2>";
					s += "<p><b>Location: " + event.venue.address.address_1 + "</b><br/>";
					s += "<b>Date/Time: " + eventTime + "</b></p>";
					
					s += "<p>" + event.description.text + "</p>";
					s += "</div>";
				}
				$events.html(s);
			} else {
				$events.html("<p>Sorry, there are no upcoming events.</p>");
			}
		});
		

		
	});
	</script>
</head>
<body>
	
<h2>Upcoming Events!</h2>
<div id="events"></div>
</body>
</html>

I love Moment.js. By the way, that code to display the event is a bit brittle. For example, it assumes a venue exists when it may not have that data. It could also show more of the venue too. Basically, remember that EventBrite events are complex so you'll want to use conditionals and the like to determine what to display. And yeah, generating the layout in JavaScript like that is ugly. Check out my video series on JavaScript templating for ways to make this nicer.

I then kicked this up a notch. The person who had asked for help mentioned they wanted to display events from multiple organizations. So I built a method that lets you pass in either an org, or an array of orgs, and your key, and then use a promise to return a sorted array of events when done:

function getEvents(organizers,token) {
	var def = $.Deferred();
	if(organizers.constructor !== Array) {
		organizers = [organizers];
	}
	
	var defs = [];
	for(var i=0;i<organizers.length;i++) {
		defs.push($.get('https://www.eventbriteapi.com/v3/events/search/?token='+token+'&organizer.id='+organizers[i]+'&expand=venue'));
	}
	var data = [];
	$.when.apply($, defs).done(function() {
		// when we had one deferred, arguments is 'normal'
		// when we have 2+, its one argument array per result
		if(organizers.length === 1) {
			def.resolve(arguments[0].events);
		} else {
			for(var i=0;i<arguments.length;i++) {
				data.push.apply(data, arguments[i][0].events);
			}
			data.sort(function(a,b) {
				var aDate = new Date(a.start.utc);
				var bDate = new Date(b.start.utc);
				return aDate > bDate;
			});
			def.resolve(data);
		}
	});
	return def.promise();

}

And to use it, you can do code like this:


var token = 'NG6HEAKRAAXCL4ZGB2YV';
var org1 = '8231868522';
var org2 = '1504496266';

getEvents([org1,org2], token).then(function(res) {

Of course, I don't have any error handling in there, but if you don't tell anyone, I won't. What's nice is you could take this code and easily use it with something like FullCalendar to create a nice, large calendar on your site.

Ok, so I was going ot go ahead and post the blog, but then I figured, why not go ahead and build a FullCalendar demo. All I had to do was modify the array of events to match what FullCalendar wanted:

var token = 'NG6HEAKRAAXCL4ZGB2YV';
var org1 = '8231868522';
var org2 = '1504496266';

var $events = $("#events");


getEvents([org1,org2], token).then(function(res) {
	console.log("Result");
	//convert res to something FC can use
	for(var i=0;i<res.length;i++) {
		res[i].title = res[i].name.text;
		res[i].startOrig = res[i].start;
		res[i].start = res[i].startOrig.utc;
		res[i].endOrig = res[i].end;
		res[i].end = res[i].endOrig.utc;
	}
	console.dir(res);
	
	if(res.length) {

		$events.fullCalendar({
			header: {
				left: 'prev,next today',
				center: 'title',
				right: 'month,agendaWeek,agendaDay'
			},
			timezone:'local',
			events:res
		});
		
	} else {
	}			
});

You can run that demo here: https://static.raymondcamden.com/demos/2015/jul/22/test7.html.

Enjoy!