Import contacts from Google
Tags: javascript
Published: 2021-05-10 14:25:43

## Introduction

in this article, you will see how to add a feature to your app (I built mine in Vue) which allows users to import their contacts from their google account.

Google supports this functionality through their **People's Api**.

## Prerequisites

The first step is to create a project in google cloud platform and get the key and client id to be used in the code. You might want to save them in `.env` file.

the second step is to load the script file for google api (gapi) to your entry html file.
```html
<script src="https://apis.google.com/js/api.js"></script>
```
after which gapi will be available in `window`

## The code

I have dedicated a specific file for implementing the people api in my project that includes all the code below.

After following the steps in the prerequisite section, we can destructure gapi from window as well as the key and client id from `process.env` since they are saved in `.env` file.

```js
const { gapi } = window;
const {
  PEOPLE_KEY: peopleApiKey,
  PEOPLE_CLIENT_ID: peopleClientId,
} = process.env;
```

Now, we load the API client and auth2 library

```js
export default function getGoogleContacts() {
  // Load the API client and auth2 library
  gapi.load('client:auth2', initClient);
}
```
`getGoogleContacts` is exported as it will be called and used somewhere else in the project.

`initClient` is the function that is used to initialize the JS client library as shown:

```js
function initClient() {
  // initialize the JS client library
  gapi.client
    .init({
      apiKey: peopleApiKey,
      clientId: peopleClientId,
      // scope is a space delimited string
      scope: 'https://www.googleapis.com/auth/contacts.readonly',
    })
    .then(() => {
// will show this code down 👇
    })
    .catch((error) => console.error(error));
}
```
the `init` function takes the `apikey`, `clientId` from the project you created in google cloud platform. As well as `scope`, and you can pass more than one, however, we are only interested in the `contacts` scope.
You can see the list of scopes 👉 [People Api scopes](https://developers.google.com/people/v1/how-tos/authorizing)

the `.then` block that I skipped above includes this code
```js
      var GoogleAuth = gapi.auth2.getAuthInstance();
      // Listen for sign-in state changes.
      GoogleAuth.isSignedIn.listen(updateSigninStatus);
      // Handle the initial sign-in state.
      updateSigninStatus(GoogleAuth.isSignedIn.get());
``` 
It uses `auth2` for authentication and to allow the user to sign in and agree to import their contacts

it first checks if the user is already signed in, otherwise it brings the sign in page.
 
```js
function updateSigninStatus(isSignedIn) {
  if (isSignedIn) {
    makeApiCall();
  } else {
    GoogleAuth.signIn();
  }
}
```
if the user is signed in, we make the api call

```js
function makeApiCall() {
  // https://developers.google.com/people/api/rest/v1/people.connections/list
  gapi.client.people.people.connections
    .list({
      resourceName: 'people/me', // deprecated (required for now)
      personFields: 'emailAddresses,names,phoneNumbers',
    })
    .then((response) => {
      formatResults(response.result.connections);
    })
    .catch((error) => {
      return error.result.error.message;
    });
}
```
we specify the `resourceName` which can only be `people/me`, but I realize it is deprecated (not sure of the alternative).
we also specify the fields we want back.

## Bonus step

I have also chosen to format the response once I get it and before I commit it to the store and use it in the app.

You could potentially `console.log` the response to see how it looks like and format it however you want, but here is an example.

```js
// [{first: '', last: '', email: [], phone: []}] that is the format I want!
function formatResults(arrayComingFromPeopleApi) {
  const resources = arrayComingFromPeopleApi.map((resource) => {
    // get multiple email addresses and phone numbers if applicable
    const { emailAddresses = [], names = [], phoneNumbers = [] } = resource;
    const email = emailAddresses.map((email = {}) => email.value || '');
    const phone = phoneNumbers.map((phone = {}) => phone.value || '');
    const lastName = names.map((name = {}) => name.familyName || '');
    const firstName = names.map((name = {}) => name.givenName || '');

    return {
      first: firstName[0],
      last: lastName[0],
      email,
      phone,
    };
  });
  // commit the resources to the store
}
```

## References
https://github.com/google/google-api-javascript-client