Synchronize agent availability with your Google Calendar
Don't be disturbed with calls when you jump in a meeting!

In this tutorial, we will create an application that updates a user's availability on Aircall whenever an event in their Google Calendar begins and ends.

The following video demonstrates how, at the start of My Meeting on Google Calendar, the user's availability on Aircall goes from available to unavailable and vice versa when the event ends a minute later.

 

Getting started

Before we begin coding, we need to have:

  1. A server running a backend application. Because it will subscribe to a webhook, we'll need to use something like Ngrok to create an SSH tunnel pointing to our local environment.
  2. An app and registered domain set up on Google's Developer Console. Be sure to get CLIENT_ID and CLIENT_SECRET in your app in order to make API calls. Go here for more info.
  3. Google auth credentials for your users, in order to retrieve their calendar events. You can go here to read about how to get them.
  4. An Aircall account - sign up here if you don't have one yet.
  5. Your API ID and your API Token. You can see your id and get a token in the Company section of the Aircall Dashboard.

Step by step

Now that we are all setup, here are the steps we are going to follow:

  1. Get the user's Google Calendar Events via the Google Calendar API
  2. Subscribe to Event push notifications, in case the user updates their events
  3. POST to the /users endpoint on the Aircall API to update a user's availability based on event start and end times

1. Get a user's calendar events

We'll want to retrieve a user's Google Calendar events via the Calendar API. For the purposes of this tutorial, we'll fetch all of the user's events right off the bat. This isn't the most efficient solution as the user could have hundreds of events. A better solution would be to schedule a cron job that, once a week, fetches the events for the upcoming week and creates GoogleCalendarEvent records in our database so that we can set availabilities accordingly.

We're using Ruby and the httparty gem here, but feel free to use whichever language/gem/package you'd like!

ruby
require 'httparty' # get a list of the user's calendars def get_calendar_list url = 'https://www.googleapis.com/calendar/v3/users/me/calendarList' HTTParty.get( url, headers: { 'Authorization' => "Bearer #{@user.google_oauth_token}" } ) end # get all the events from a user's calendar def get_events # we're assuming the first calendar is the one we want calendar = get_calendar_list['items'].first return if calendar.nil? url = "https://www.googleapis.com/calendar/v3/calendars/#{calendar['id']}/events" HTTParty.get( url, headers: { 'Authorization' => "Bearer #{@user.google_oauth_token}" } ) end

The @user variable should be whatever your current user is, and this code assumes they've already authenticated on your app. Check step 3 in the setup for more info on authentication.

Each event hash will have start and end keys:

json
{ "id": "465qfgq7p5mcvdpm9kfsgn0i3f", "summary": "My Meeting", "status": "confirmed", "start": { "dateTime": "2018-03-21T14:00:00+01:00" }, "end": { "dateTime": "2018-03-21T14:15:00+01:00" } ... }

You can save these to your database, perhaps as GoogleCalendarEvent records so that your application (with the help of a cron job) can later know when to sync the user's availability.

2. Subscribe to event push notifications

In case a user changes any events on their calendar, we're going to subscribe to Calendar API Push Notifications so we can keep the start and end times updated.

ruby
require 'httparty' def subscribe_calendar_notifications url = "https://www.googleapis.com/calendar/v3/calendars/#{@user.google_calendar_id}/events/watch" HTTParty.post( url, headers: { 'Authorization' => "Bearer #{@user.google_oauth_token}" }, body: { id: 'unique-channel-id', type: 'web_hook', address: '/webhooks/google/notifications' } ) end

Make sure id is unique within your app, and the address should be whatever your current NGROK url is, along with a path to receive webhook events.

You only have to subscribe to a particular calendar once, so you might want to do this right after the user authenticates their Google account. Let's say this happens in a callback method within GoogleController

ruby
# app/controllers/google_controller.rb def auth_callback if user_authenticated? # logic to verify successful authentication + save credentials subscribe_calendar_notifications end end

Now that our webhook is subscribed, we need to handle the requests that we receive. Here, we'll demonstrate how to set up the Webhook as a Rack app, just to give you an idea on how to handle requests.

ruby
# config.ru require './app' run App.new
ruby
# app.rb require 'rack' require 'json' class App def initialize @app = Rack::Builder.new do map '/webhooks/google/notifications' do run Proc.new { |env| req = Rack::Request.new(env) body = JSON.parse(req.body.read) if req.body.read.present? headers = {} env.select {|k,v| k.start_with? 'HTTP_'} .collect {|key, val| [key.sub(/^HTTP_/, ''), val]} .each {|key, val| headers[key] = val} case headers['X_GOOG_RESOURCE_STATE'] when 'sync' # we receive this message to indicate that notifications are starting, # and could retrieve all events here if we wanted to puts 'SYNC!' when 'exists' # the calendar has changed, so we would want to retrieve all events # again and verify that the start and end times for each event haven't # changed, and update our records if they have end ['200', {'Content-Type' => 'text/html'}, ['ok']] } end end end end

3. Update a user's availability via the Aircall API

Now that have a user's Calendar events and we're sure we have up-to-date start and end times, we can set up workers to update their availability on Aircall via the API.

It's up to you how you set up your application's cron jobs, so we'll just give you an example of a scheduler that runs Sidekiq workers AvailabilityWorker for all events for the current day. We'll use the clockwork gem, a scheduler process that is easily configurable to spawn workers when we need them. Read here if you're unfamiliar with cron jobs.

ruby
class AvailabilityWorker include Sidekiq::Worker def perform(user_aircall_id, event_end_time, is_occurring = true) status = is_occurring ? 'unavailable' : 'available' url = "https://api.aircall.io/v1/users/#{user_aircall_id}" HTTParty.post( url, basic_auth: { username: ENV['AIRCALL_API_ID'], password: ENV['AIRCALL_API_TOKEN'] }, availability_status: status ) # queue another worker for when the event ends AvailabilityWorker.perform_at(event_end_time, user_aircall_id, event_end_time, false) if is_occurring end end
ruby
# clock.rb require 'clockwork' include Clockwork every 1.day, 'job.calendar_availabilities' do events = calendar_events_for_user # logic to retrieve events for one or many users events.each do |event| # queue the worker to spawn once the event starts AvailabilityWorker.perform_at(event.starts_at, event.user_aircall_id, event.ends_at, true) end end

And voilà! Now your user's Calendar meetings can reflect their availability status on Aircall, preventing unnecessary missed calls. There's plenty more possible with the Google Calendar API so feel free to dig deeper with this integration!

Error handling has not been implemented in the above code examples to make the code easier to read.
Don't go deploying this in a production environment!

We wrote other tutorials to help you out
building awesome integrations

Discover them now