Javascript to Display a Public Google Calendar as a List on your Website

One of our projects required displaying a list of upcoming events on a website. We wanted to enable the site editor to edit these events. We are working in OctoberCMS and it would have been fairly easy to just create a static list or a table, and have the user edit that in the backend, or even to use a plugin to this end; we decided that the best approach would be to tap into the power of google calendars.

The script only works with a public google calendar. This shouldn't be an issue since the website is public so the information in the calendar will be shared online anyway. And it makes the script much simpler, since we don't need to do any kind of fancy authentication.

  1. Google only allows a certain number of requests to its services, so you will need to create a google developer account. Then, enable the Calendar API, and also create a new public API Key - this is what google will use to track your API usage.
  2. Create a new google calendar and set it as public
Make the calendar public

3. Get the calendar ID

Your Calendar ID

4. Create an element in your page where you will load the retrieved calendar events

<div id="wellness-calendar"></div>

5. The script makes use of moment.js and google's JS API, so you'll need to add the following somewhere in your page to load these:

<!-- For google calendar integration -->
<script src="https://cdn.jsdelivr.net/npm/moment@2/moment.min.js"></script>
<script src="https://apis.google.com/js/api.js"></script>

6. Add the calendar script somewhere, and customize it

You will need to replace YOUR_CALENDAR_ID and YOUR_API_KEY in the script below!

<script>
		/* This solution makes use of "simple access" to google, providing only an API Key.
		* This way we can only get access to public calendars. To access a private calendar, 
		* we would need to use OAuth 2.0 access. 
		* 
		* "Simple" vs. "Authorized" access: https://developers.google.com/api-client-library/javascript/features/authentication
		* Examples of "simple" vs OAuth 2.0 access: https://developers.google.com/api-client-library/javascript/samples/samples#authorizing-and-making-authorized-requests
		*
		* We will make use of "Option 1: Load the API discovery document, then assemble the request." 
		* as described in https://developers.google.com/api-client-library/javascript/start/start-js
		*/
		function printCalendar() {
			// The "Calendar ID" from your calendar settings page, "Calendar Integration" secion:
			var calendarId = 'YOUR_CALENDAR_ID@group.calendar.google.com';

			// 1. Create a project using google's wizzard: https://console.developers.google.com/start/api?id=calendar
			// 2. Create credentials: 
			//    a) Go to https://console.cloud.google.com/apis/credentials
			//    b) Create Credentials / API key
			//    c) Since your key will be called from any of your users' browsers, set "Application restrictions" to "None", 
			//       leave "Website restrictions" blank; you may optionally set "API restrictions" to "Google Calendar API"
			var apiKey = 'YOUR_API_KEY';
			// You can get a list of time zones from here: http://www.timezoneconverter.com/cgi-bin/zonehelp
			var userTimeZone = "Europe/Budapest";

			// Initializes the client with the API key and the Translate API.
			gapi.client.init({
				'apiKey': apiKey,
				// Discovery docs docs: https://developers.google.com/api-client-library/javascript/features/discovery
				'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
			}).then(function () {
				// Use Google's "apis-explorer" for research: https://developers.google.com/apis-explorer/#s/calendar/v3/
				// Events: list API docs: https://developers.google.com/calendar/v3/reference/events/list
				return gapi.client.calendar.events.list({
					'calendarId': calendarId,
					'timeZone': userTimeZone,
					'singleEvents': true,
					'timeMin': (new Date()).toISOString(), //gathers only events not happened yet
					'maxResults': 20,
					'orderBy': 'startTime'
				});
			}).then(function (response) {
				if (response.result.items) {
					var calendarRows = ['<table class="wellness-calendar"><tbody>'];
					response.result.items.forEach(function(entry) {
						var startsAt = moment(entry.start.dateTime).format("L") + ' ' + moment(entry.start.dateTime).format("LT");
						var endsAt = moment(entry.end.dateTime).format("LT");
						calendarRows.push(`<tr><td>${startsAt} - ${endsAt}</td><td>${entry.summary}</td></tr>`);
					});
					calendarRows.push('</tbody></table>');
					$('#wellness-calendar').html(calendarRows.join(""));
				}
			}, function (reason) {
				console.log('Error: ' + reason.result.error.message);
			});
		};

		// Loads the JavaScript client library and invokes `start` afterwards.
		gapi.load('client', printCalendar);
	</script>
    ```

The script is very straightforward, so you should be able  to customize it easily to fit your needs!

One issue is that you are making your google calendar API key public. This shouldn't really be an issue, but if you're concerned, an alternative solution would be to do the whole thing on the server side (for example, in PHP) and only serve the results to the user. For that you'll also want to take a look at the Google API Client Library for PHP.

Alternatively, here are some other solutions I found while doing my research: