I recently worked on a project where we needed to synchronise contact data between Highrise CRM (the source), Basecamp (for project management) and Google Shared Contacts (for email). This is a common issue for small businesses – how to keep disparate systems in sync. There are already some proprietary systems out there which help with this but they didn’t fulfil the needs of this client so we opted for a custom tool.
I’ll write up the steps I took to get all of this working in a series of posts, but the overall architecture is thus:
At the time of writing I determined the feasibility of synchronising all of these three systems by looking in detail at the APIs provided. I’ve summarised my findings here:
Google Shared Contacts
It’s worth pointing out that we needed to load up NOT Google’s personal contacts, but the domain shared contacts. This is a repository of contacts that Google provides on its Google Apps product, and works like a Global Address List, providing a single store of contact data to all domain users. However, for some puzzling reason Google does not provide any user interface to manage this database. Instead you must use the Google Shared Contacts API.
IMPORTANT POINT: I got very confused as to which versions of Google Apps supports the Google Shared Contacts API. Even though the documentation pages state that it is only supported by Apps for Business (Premium) and Education, the confusing point is that YOU CAN EXECUTE THE API CALLS SUCCESSFULLY and the data IS PERSISTED.
What I later discovered was that although all of the API calls work, the data is not exposed in Google Apps. This is very frustrating and I wish Google would make this clearer in their documentation.
Also don’t get confused between the Google Contacts Data API and the Google Shared Contacts API.
Highrise & Basecamp
Both of these products are made by 37Signals, and if you’ve ever read their books, you’ll know that they are keen proponents of open systems. They have well documented APIs which are very easy to get up and working with.
However, when you start to use them, you discover that some key elements are missing. The APIs they have provided allow you to get all information out, but when it comes to creating data, the calls just aren’t there. Despite numerous forum posts, 37Signals have not yet given good reasons for the lack of these API calls.
To get around this, I wrote a cheeky HTTP GET, Parse and Re-POST class which effectively walks through the front-end of the site programmatically, as if it were a standard user. Whilst this has been very stable so far, if either of the products publish changes to their UI then this code may need modification.
I wrote all of the code in PHP 5, so all the samples here will be in PHP, but you could easily apply the concepts to different programming languages.
I built singelton classes for each of the products, and then a controlling class to tie them up all to achieve the synchronisation. I used PHP curl() to do the web requests, and for the Google API stuff I used Zend’s GData classes to speed up the development.
In order to synchronise these systems I took the following approach:
- Get all Highrise Contacts
- Add to Basecamp, storing the IDs of the two data objects in a synchronisation file
- Add to Google Contacts, storing the ID of the Highrise Contact in the Notes field
In the next post I’ll start introducing the code I wrote to hook up to the Basecamp and Highrise APIs.