I would like to develop a "Add to contacts" button for a webpage, much like the "add to calendar - Google, ICal, Outlook" type buttons that you see on webinar and event pages like this one.
I started investigating Google Contacts, as I use that. I started building a form to submit an application/atom+xml to the URL they talk about in the help files here and a similar question for Google on Stack.
I figure creating this is a Open Source like service to the community, some expert help would be appreciated as I tinker with it. I am asking here for that contribution.
My rough code, that isn't working
function SendToGoogle() { var url = "https://www.google.com/m8/feeds/contacts/default/full"; var data = contactData(); alert(data); /* $.post(url, data, function(data, status){ alert("Data: " + data + "\nStatus: " + status); }); */ $.ajax({type: "POST", url: url, dataType: "xml", contentType: "application/atom+xml", cache: false, async: true, crossDomain: true, success: function(data, status){ alert("Data: " + data + "\nStatus: " + status)} }) } //end SendToGoogle function contactData() { return ' Elizabeth Bennet Elizabeth Bennet Notes (206)555-1212 (206)555-1213 Mountain View 1600 Amphitheatre Pkwy CA 94043 United States 1600 Amphitheatre Pkwy Mountain View '; } //end contactData
The proof is in the pudding so before you torture yourself reading this long post: Create Contacts Test Site got it working :) If you have the webtool's console open you can see we get back the contact Person resource, and Elizabeth Bennet will now be in your contacts!
Oh by the way when authenticating as the user google will complain about it not being safe both on my little website and your local version, just click advanced and continue. ( Google will do this until you submit your OAuth for verification by their team so good on a final product but... )
So in the google help docs at the very top we see this:
Note: For read and write access to users' contacts, use the People API, which provides both contact and profile information using JSON instead of the older GData protocol.
So it really seems like the correct answer here is to move to the People API. I spent some time looking into it and have a cursory answer for you.
I found this example page which works out the majority of what you want. If you follow it exactly you will get a local version working in javascript connecting to their api which does allow us to createContacts.
We have to setup an api app within google's api to essentially authenticate this process.
Once we do that we can setup buttons that request for the user to accept authentication ( allow us to create a contact for them ).
The fun is changing their code, which simply puts out the top 10 users for the user on the page into creating the contact.
There does appear ways to perhaps do it straight with a regular http request after you have gotten the user's permission but I found it quicker to work with their crazy api setup.
We need to know how to setup the gapi.client.people.people.createContact
api call and it takes a Person resource. That resource is handy to click around on to see how we can setup the person resource categories.
Here is where we can play with the api before we attempt to put it on our webpage. In the right panel there is a headline of:
Try this API
Right next to it there is a little box which expands the area so we can more easily play with the api. There is a JavaScript option in the top right of that to give an attempted look at the JavaScript equivalent of the request we are doing.
On the left we have the request body which lets us put in the details to our createContacts api request. So for your example if you put in:
{
"names": [
{
"givenName": "Elizabeth",
"familyName": "Bennet"
}
],
"phoneNumbers": [
{
"type": "home",
"value": "(206)555-1212"
},
{
"type": "cell",
"value": "(206)555-1213"
}
],
"addresses": [
{
"type": "home",
"streetAddress": "1600 Amphitheatre Pkwy",
"postalCode": "94043",
"country": "United States",
"city": "Mountain View",
"region": "California"
}
]
}
In that left box you can see it input it into the javascript createContacts request on the right.
Now that code isn't perfect for how we want to keep ourselves and our user authenticated so we will cherry pick out two main things:
.signIn({scope: "https://www.googleapis.com/auth/contacts"})
That scope tells the api essentially what we want to access for the user.
So putting it all together now:
<!DOCTYPE html>
<html>
<head>
<title>People API Quickstart</title>
<meta charset="utf-8" />
</head>
<body>
<p>People API Quickstart</p>
<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" style="display: none;">Authorize</button>
<button id="signout_button" style="display: none;">Sign Out</button>
<button id="contact_button" style="display: none;">Create Contact</button>
<pre id="content" style="white-space: pre-wrap;"></pre>
<script type="text/javascript">
// Client ID and API key from the Developer Console
var CLIENT_ID = '< YOUR CLIENT ID HERE! >';
var API_KEY = '< YOUR API KEY HERE! >';
// Array of API discovery doc URLs for APIs used by the quickstart
var DISCOVERY_DOCS = ["https://www.googleapis.com/discovery/v1/apis/people/v1/rest"];
// Authorization scopes required by the API; multiple scopes can be
// included, separated by spaces.
var SCOPES = "https://www.googleapis.com/auth/contacts";
var authorizeButton = document.getElementById('authorize_button');
var signoutButton = document.getElementById('signout_button');
var contactButton = document.getElementById('contact_button');
/**
* On load, called to load the auth2 library and API client library.
*/
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
/**
* Initializes the API client library and sets up sign-in state
* listeners.
*/
function initClient() {
gapi.client.init({
apiKey: API_KEY,
clientId: CLIENT_ID,
discoveryDocs: DISCOVERY_DOCS,
scope: SCOPES
}).then(function () {
// Listen for sign-in state changes.
gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus);
// Handle the initial sign-in state.
updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
authorizeButton.onclick = handleAuthClick;
signoutButton.onclick = handleSignoutClick;
contactButton.onclick = handleContactClick;
}, function(error) {
appendPre(JSON.stringify(error, null, 2));
});
}
/**
* Called when the signed in status changes, to update the UI
* appropriately. After a sign-in, the API is called.
*/
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
authorizeButton.style.display = 'none';
signoutButton.style.display = 'block';
contactButton.style.display = 'block';
} else {
authorizeButton.style.display = 'block';
signoutButton.style.display = 'none';
}
}
/**
* Sign in the user upon button click.
*/
function handleAuthClick(event) {
gapi.auth2.getAuthInstance().signIn();
}
/**
* Sign out the user upon button click.
*/
function handleSignoutClick(event) {
gapi.auth2.getAuthInstance().signOut();
}
/**
* Create a contact upon button click.
*/
function handleContactClick() {
gapi.client.people.people.createContact({
"resource": {
"names": [
{
"givenName": "Elizabeth",
"familyName": "Bennet"
}
],
"phoneNumbers": [
{
"type": "home",
"value": "(206)555-1212"
.signIn({scope: "https://www.googleapis.com/auth/contacts"}) },
{
"type": "cell",
"value": "(206)555-1213"
}
],
"addresses": [
{
"type": "home",
"streetAddress": "1600 Amphitheatre Pkwy",
"postalCode": "94043",
"country": "United States",
"city": "Mountain View",
"region": "California"
}
]
}
}).then(function(response) {
// Handle the results here (response.result has the parsed body).
console.log("Response", response);
},
function(err) { console.error("Execute error", err); });
}
/**
* Append a pre element to the body containing the given message
* as its text node. Used to display the results of the API call.
*
* @param {string} message Text to be placed in pre element.
*/
function appendPre(message) {
var pre = document.getElementById('content');
var textContent = document.createTextNode(message + '\n');
pre.appendChild(textContent);
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
</body>
</html>
The client and api variables at the top is where you put in your keys after walking through their steps on the quickstart page.
So obviously the buttons and how things work can be changed around but this was just to prove it working :P
Here is my github on it: GitHub you only need to pay attention to the index.html the php was so i could put up the little test website to show you.
Google APIs strike again!
Hope this helps, hit me up if there is anything else!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With