Advertisement
  1. Code
  2. Yii
Code

Building Your Startup: Importing With the Google Contacts API

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Building Your Startup With PHP.
Building Your Startup: Completing Group Scheduling
Building Your Startup: Error Logging
Final product image
What You'll Be Creating

This tutorial is part of the Building Your Startup With PHP series on Envato Tuts+. In this series, I'm guiding you through launching a startup from concept to reality using my Meeting Planner app as a real-life example. Every step along the way, I'll release the Meeting Planner code as open-source examples you can learn from. I'll also address startup-related business issues as they arise.

Introduction

Good morning. Today, I'll walk you through how I used the Google API to import people's contacts into Meeting Planner. The goal is to make it faster for people to invite their friends to meetings.

If you haven't tried scheduling a meeting with Meeting Planner, please give it a try. If you use your Google account to sign up, you can visit the Friends page above and Import Your Google Contacts. Share your thoughts and feedback in the comments below. 

I do participate in the discussions, but you can also reach me @reifman on Twitter (recently my account was verified so I must be as cool as Justin Beebert (note to editorial gods—I'm confident in this spelling. I think it's right. Leave it.) I'm always open to new feature ideas for Meeting Planner as well as suggestions for future series episodes.

As a reminder, all the code for Meeting Planner is provided as open source and written in the Yii2 Framework for PHP. If you'd like to learn more about Yii2, check out my parallel series Programming With Yii2

Thinking About Google Contacts Integration

The Friends Page

Many people have thousands of contacts in their Google account—and few are important to them. But, for most, there's no way to discern which are and which aren't.

I believe that the size of the User table in Meeting Planner impacts the service's overall performance. I did not want to import contacts that may never be relevant into the User table.

This created some complications both in UX and code where people look for and access their friends in the service.

I decided in the end to create a separate table for contacts and to actually show this separately in the user interface for now.

Building Startups Google Contacts API - List of Imported Contacts on Friends Page

Choosing Participants for Meetings

Where all of this leads is that it will become easier for people to add friends from their contacts by just typing the first few characters. I'm using a Typeahead widget in the Add Participants pop-up shown below:

Building Startups Google Contacts API - Add a Participant Form

After I've imported my Google Contacts, they are integrated with my friends (people I've already invited to meetings or been invited by).

In this case, I began to type sar and a whole bunch of Sar- prefix names appear:

Building Startups Google Contacts API - Dropdown from Friend and Address Table

Finding anyone to invite to a meeting from your Google Contacts becomes quite fast and easy (until you add a lot of them, which I mention further below).

Privacy Issues

I also don't want to abuse people's trusts by misusing their thousands of Contacts. At this time, we won't even offer people the opportunity to invite all of their Google contacts to Meeting Planner, though we might offer this in the future. We certainly won't bulk email them without permission.

Writing the Code

If you haven't yet, peek at Building Your Startup With PHP: Simplifying Onramp With OAuth. That's the episode where I first authenticated the Google APIs for OAuth Login and Sign-up.

Google is careful about security with their APIs. In light of what's recently happened with the Yahoo hacks, I appreciate this more deeply. However, this makes their APIs more difficult than others to authenticate and work with.

In fact, I found the Google Contacts API flow some of the most confusing, frustrating and difficult that I've had to write. And Google API's disfavor PHP programmers—we're the last to get sample code.

Let's dive in.

Creating the Address Table

Since there is already a UserContact table for the user's phone and Skype addresses, I decided to call the table Address. Here's the migration to create it:

Of course, I used Yii's Gii to help me with the controller, model, and views. This has been covered earlier in the startup series

Extending Google API Authentication

You may remember the Google Credentials page in the tutorial mentioned above:

Building Startups Google Contacts API - Google API Credentials Form

You can find it from the Google Developers Console.

You have to add URLs for all of your environments—development, staging, production, etc.—and for every controller and method. This complicates the efforts to work with its Contacts API, but also probably better secures people's data.

Building Startups Google Contacts API - Google API Credentials Form lower part

Importing Google Contacts

Here's the Google Contacts API v3.0. I did not notice when I began writing the code that they now recommend the People API for read-only access. Unfortunately, my code is using the read/write API. Okay, so I'm not a genius. Entrepreneurs rarely are—even Bill Gates says he was just lucky. 

In general, I found the Google Contacts API to be one of the more confusing and difficult APIs I've ever used.

If I had a higher level of expertise at Google API development or spent more time working on this, I might have found a simpler approach. But, from what I could tell, it was important that you do everything with the API from one URL. In my case https://meetingplanner.io/address/import.

And Google returns keys and redirects you back to this URL repeatedly—so you need to be watching for the state of the API and working around this.

I'm presuming this is all done to increase security, but it requires state management built in to what would otherwise be simple API requests. State management can save time, but only if the documentation and sample code are good. In this case, for PHP, they're not.

Getting Started

Let's look at AddressController.php actionImport():

Above, I'm watching for whether Google wants to reset its API tokens. In this case, I remove the cookies I'd stored them in and redirect back to the method to start over.

Making the Request for a Token

Below, I'm making my first request to Google via its PHP client library:

The Google PHP library is in beta. In fact, PHP is generally an afterthought to Google. So it's not always easy working in PHP with their APIs.

Notice above that Google's $redirect_uri is the same method again: 'address/import'

Next, we try to place the token from the query parameter in a cookie:

If you do get the code from Google, you have to set it in the cookie and redirect to the page again. That's odd to me.

Joyfully, I also found that if I didn't create a loop back when the code was missing—to go back to the same page again, it wouldn't work consistently.

Then, we construct and ask Google to present to the user a permission dialog to give Meeting Planner access to their contacts:

Building Startups Google Contacts API - Google Asks User for Permissions

I had to add a lot of error management to figure out why it wasn't working and to get all of this to work consistently.

You guessed it, if there's an error condition, I would often redirect to this same controller method.

Processing Returned Data

When everything works, the fun, easy code gets to process the data. Currently, we grab 1,000 entries five times, repeatedly constructing pagination requests that, of course, are sent back to this URL:

Translating Google's XML (which is also complex, with odd variable names for PHP developers, e.g. keys such as $contact['gd$email'][0]['address'] with a dollar sign in the middle.

Below, we're making each request, running through the JSON data, and grabbing contact names to add to the Address table:

Working with the Google Contacts API was super difficult, not well documented, and wasted a lot of time for me. While I've worked with a lot of APIs successfully, I know I'm not an expert at this. Due to security concerns, I don't really want to beat up on Google over this—in a lot of these cases, they probably know why they do things certain ways.

But it's okay to poke a little fun, right?

Firstly, everyone at Google is a genius, and they proved it again by acquiring API.ai, a brilliant service that links its Sign Up button to its Login Form. Really, they did:

I'm sure Google's due diligence team saw genius in it that remains beyond mortals like me. They must have said, "Wow, the API.ai programmers are geniuses like our AdSense and DFP teams! Let's add them to the Alphabet!"

Since I may be talking to angel and VC investors about Meeting Planner in the future, I want to be humble. But I would be horrified if my home page did this and one of my prospective investors noticed.

The new Alphabet (Google's new parent company) is so forgiving.

Extending the Add Participants Form

Finally, let's just look at the code behind the extended Add Participants Form. Basically, I'm grabbing emails from the Friends table and then emails from the Address table:

However, the option value is just the email since it would have become more complicated to designate which kind of friend this is (from Friend or from Address table).

I'm not super proud of the code and approach above, but rushing towards the beta release, I made compromises to get it done.

With 5,000 Google Contacts in my friends dropdown, performance is slower. I probably need to better link the control to an AJAX database search soon.

And I wasted a lot of time early on trying to extend the Friends table to include people who I've invited as well as Google Contacts. However, this turned into a mess of difficult-to-manage related database queries. The User table relations from the Friends table started breaking for Contacts rows where they'd be null, and this actually turned out to be very difficult to resolve. Managing the removal of existing foreign keys up and down through migrations is treacherous too.

Closing Thoughts

These features were great examples of the challenges of relying on APIs with poor documentation in your chosen language and making compromises in code architecture for the moment to launch features to a release schedule (opting not to cut them).

And there are certainly still issues with the Participant add performance and Friends page UX that need to be fixed. 

Honestly, the scope of Meeting Planner has reached the point where doing this as one person is daunting. And it would be helpful to have more resources (i.e. team members.)

Finally, if you haven't yet, go schedule your first meeting with Meeting Planner now! Let me know what you think in the comments below. You can also reach out to me @reifman. I'm always open to new feature ideas and topic suggestions for future tutorials.

A tutorial on crowdfunding is also in the works, so please follow our WeFunder Meeting Planner page.

Stay tuned for all of this and more upcoming tutorials by checking out the Building Your Startup With PHP series

Related Links

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.