Google+ Platform

Adding Google+ to your Facebook Integration

Introduction

Google+ Sign-In and the Google+ platform lets users sign in to your app or website with their Google credentials and build engaging experiences across desktop and mobile. If you are a developer with experience on the Facebook platform, this guide helps you integrate Google+ into your new or existing products. You will set up your project, learn to manage the intricacies of having multiple social identity providers, and translate the features of your Facebook integration to the Google+ platform. You will also see a sample app that demonstrates how to implement all of the information below.

Getting Started

Create a new project

To begin integrating Google+ into your app, you must create a Google APIs Console project and get a client ID and client secret. If you have managed an application on Facebook's Developer Dashboard, this process should be familiar to you. With Google, you can manage all of your projects and API access through the Google APIs Console.

To get started, create a Google APIs Console project, OAuth 2.0 client ID, and register your JavaScript origins:

  1. Go to the Google Developers Console.
  2. Select a project, or create a new one.
  3. In the sidebar on the left, select APIs & auth. APIs is automatically selected.
  4. In the displayed list of APIs, make sure the Google+ API status is set to ON.
  5. In the sidebar on the left, select Credentials.
  6. In the OAuth section of the page, select Create New Client ID.

    In the resulting Create Client ID dialog box, register the origins where your app is allowed to access the Google APIs. The origin is the unique combination of protocol, hostname, and port.

    1. In the Application type section of the dialog, select Web application.
    2. In the Authorized JavaScript origins field, enter the origin for your app. You can enter multiple origins to allow for your app to run on different protocols, domains, or subdomains. Wildcards are not allowed. In the example below, the second URL could be a production URL.
      http://localhost:8080
      http://myproductionurl.example.com
    3. Select Create Client ID.
    4. In the resulting Client ID for web application panel, note or copy the Client ID and Client secret that your app will need to use to access the APIs.

Load the JavaScript client library

The quickest way to get started with Google+ on the web is to use the JavaScript client library. The Google+ JavaScript client library is contained in a single script called plusone.js, which you must include on any page that will access Google+ features or APIs from JavaScript. Place the following code before the closing </body> tag in order to asynchronously load the client library:

<script>
  // Asynchronously load the client library
  (function() {
     var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
     po.src = 'https://apis.google.com/js/client:plusone.js';
     var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
   })();
  // Asynchronously load the Facebook SDK if necessary
  ...
</script>

To fire a callback when the client library has loaded, add ?onLoad=loadCallback to the end of the src attribute in the code above and then define a function named loadCallback() in your JavaScript.

The Google+ Sign-In button

Adding the button

On the Facebook platform you can choose between making your own button and using JavaScript to initiate sign-in, or using Facebook's Login Button plugin. With Google+, you can customize the Google+ Sign-In button without writing additional JavaScript or HTML. The following code includes the button on your page:

<span id="signinButton">
    <span
      class="g-signin"
      data-callback="signinCallback"
      data-clientid="YOUR_CLIENT_ID"
      data-cookiepolicy="single_host_origin"
      data-scope="https://www.googleapis.com/auth/plus.login">
    </span>
</span>

The button markup contains a number of parameters that you need to specify, including your app's client ID, the scopes that you are requesting, and the function to call after the SDK has retrieved the current user's authorization status. For now just think of data-scope like the permissions that you request on Facebook. Data-scope controls what user information you can access and is covered in more detail below. If you omit the data-scope attribute, it defaults to https://www.googleapis.com/auth/plus.login. For information on how to customize the look and feel of the button, see customizing the sign-in button.

To begin authentication with Facebook, you must define the window.fbAsyncInit(...) function and then call FB.init(...). Including the Google+ Sign-In button markup on your page automatically performs the equivalent initialization. The callback function defined in the button markup, signinCallback in this case, is called by the client library when the user's authorization status has been determined.

<script>
  function signinCallback(authResult) {
    if (authResult['access_token']) {
      // Signed in with Google+, you can proceed as usual
    } else if (authResult['error']) {
      // There was an error signing the user in
    }
  }
</script>

In order to initiate login on Facebook, you probably called the FB.login(...) or FB.getLoginStatus(...) methods to determine the user's authorization status. On the Google+ platform authorization state is managed through the signinCallback function and the entire process can be automatic if the user has signed in to your application before. At any time, if signinCallback is called with a successful response, you can proceed to personalize the experience and use the Google+ APIs immediately. This automatic callback reduces user friction and provides the best experience for your users.

Managing Google+ and Facebook together

Consider that you have a page that displays both a Google+ Sign-In button and a Facebook Login button. The following markup defines the two buttons:

<!-- Google+ Sign-In button -->
<span
  class="g-signin"
  ...
  data-callback="signinCallback"
  ...></span>
<!-- Facebook Login Button -->
<button id="fb-login">Login With Facebook</button>

You want to give your users a seamless authorization experience, but as a developer there are a lot of different authorization states that you need to handle. What if the user is signed in with both providers? What if the user chooses a different provider each time they visit your app? In order to properly respond to all possible situations, consider using the following code, or a similar pattern:

<script>
  // Keep track of authorization states for both providers.
  var AuthStates = {
    google: null,
    facebook: null
  }

  // Set up the click listener for the Facebook button.
  $(document).ready(function() {
    $("#fb-login").click(function() {
      FB.login(function(response) {
        AuthStates.facebook = response;
        chooseAuthProvider();
    });
  });

  /**
   * Authenticate with the preferred social identity provider.
   */
  function chooseAuthProvider() {
    // The script has already made calls to both Google and Facebook (through signinCallback and
    //  FB.getLoginStatus) so this does not hang on user interaction.  The order of social provider
    //  choice below (Google, then Facebook) can be changed according to developer preference
    //  without affecting functionality.
    if (AuthStates.google && AuthStates.facebook) {
      if (AuthStates.google['access_token']) {
        // Signed in with Google, you can now use Google+ APIs.
      } else if (AuthStates.facebook.authResponse) {
        // Not signed in with Google, but signed in with Facebook,
        //  you can now use the Facebook SDK.
      } else {
        // Not signed in with anyone, wait until the user chooses a social provider.
      }
    }
  }

  /**
   * Called when the Google+ client library reports authorization status.
   */
  function signinCallback(authResult) {
    AuthStates.google = authResult;
    chooseAuthProvider();
  }

  /**
   * Called when the Facebook SDK is loaded.
   */
  window.fbAsyncInit = function() {
    FB.init({
      appId: 'YOUR_APP_ID',
      status: true,
      cookie: true,
      xfbml: true
    });

    // Retrieve auth status from the Facebook SDK.
    FB.getLoginStatus(function(response) {
      AuthStatus.facebook = response;
      chooseAuthProvider();
    });
  }
</script>

It is important to check authorization state on every page with social features. You can include the code above on every page, and display the sign-in buttons when the user is not signed in with any social providers.

At this point, your user is automatically logged in to Google when possible, and logged into Facebook when they are not signed in with Google. The code also responds to changes in authorization status for the entire life of the page, not just on first load. This code also helps to avoid race conditions by waiting until both providers report authorization status before making a decision on how to authenticate the user. You can add more cases to the chooseAuthProvider method based on the specific needs of your application.

Server-Side

Storing authorization

After the user signs in with the client-side flow, you might want to store the user's information on your web server. Start by storing the access_token, the access token's expires_at time, and some basic personal information such as name. You also want to store the refresh_token, which is discussed below. Storing this information is straightforward when you have a single social identity provider, like Google+ or Facebook, but is more complicated when you introduce multiple providers.

In order to create a robust multi-provider app, you must separate the concept of Identity from your User object, because it is now possible for a User to have an Identity from each provider. Consider a User table from a single-provider application, which might have a schema like this:

User
fieldtype
idint
namestring
emailstring
access_tokenstring
uidstring
expires_atint

In this architecture, the user's authorization information is stored in the main user record, which doesn't leave much space for managing multiple identity providers. If we create a new Identity model and link it to the User model with a foreign_key, we can have a more flexible schema that looks like this:

User
fieldtype
idint
Identity
fieldtype
user_idint
providerstring
namestring
emailstring
access_tokenstring
refresh_tokenstring
uidstring
expires_atint

Now our Users are related to our Identities with a one-to-many relationship, and we can add as many social identity providers as we want without further modifying our database schema. Each Identity has the same information and is uniquely identified by a user_id, uid, and provider ("google", "facebook", etc.). The user_id ties the Identity to a unique User on your server while the uid is the user's unique identifer from the social identity provider. The Identity model also has the added benefit of separating possible information conflicts, such as if the user lists a different name on Google+ than on Facebook. Now just add the data-accesstype="offline" attribute to the Sign-In button, follow the token instructions below to get an access_token and refresh_token, and store all of the information in your new Identity model. This strategy works with both Facebook and Google+ without complicating your server-side logic or affecting your user experience.

In the schema above, the refresh_token field is only used for Google+ Identities and is unused for Facebook. As you add more identity providers with unique needs, it is more flexible to move to a more general Identity schema. For instance, you could have an extras field that stores a JSON object containing all of the provider-specific attributes of the Identity, such as the refresh_token.

When a user initiates authorization with Google+ or with Facebook, they might already have an Identity on your system from another social provider. Instead of creating an entirely new User model, join the new Identity to an existing User. One simple way of doing this is to check for an Identity with the same email and merge with the User that owns the existing Identity because this uniquel identifies a user. Don't link a new Identity to an existing user unless you are absolutely sure that it is the same person because you don't want to reveal User information to the wrong person.

The Identity model presented above allows for a variety of different methods for managing multiple-provider accounts. The best method is to have the user voluntarily link accounts. For example, when a user is signed in with Google, you could offer a "Link Facebook Account" button on the user profile page. This flow ensures that the user is always aware of which social identities he/she has associated with your app at any time.

In addition to making your code more flexible and extensible, the Identity model makes it much easier to comply with the terms of service for both Google+ and Facebook. For example, the Google+ personal information policy states that you must "give users a reasonably convenient way to delete any of their personal information you have obtained from the API". By separating information from Google+ and Facebook into distinct identities, you can easily target and delete the information from one platform without compromising the information that you have collected from the other.

Tokens

While both Facebook and Google use OAuth 2.0 for authentication, you must be aware of the subtle differences between the two providers when dealing with the OAuth access tokens.

When using the client-side flow, if the user successfully authenticates, you get an access_token which enables you to use the Google APIs that the user has approved. This token is good for one hour (3600 seconds) from the time it is issued, but is automatically replaced with a fresh token by the JavaScript client library if it detects that the token has expired while your user is still actively using the app. If you only plan to access Google+ APIs while the user is interacting with your application, you will not have to worry about token management at all.

To access Google APIs from your server while the user is offline, you need to get a longer-lasting refresh token by using the one-time-code flow. When your user signs in on the client side, you are given a code that you can send to your server. This code can be exchanged for an access_token that you can use for offline access if you set the data-accesstype="offline" attribute on your sign-in button. After you exchange this one-time code on your server, Google provides your server with a refresh token and an access token. By storing both the access_token and the refresh_token, you can use the Google API Client Libraries on your server to refresh the access_token when it expires without requiring the user to re-authorize.

Separating social and business logic

When your users can have multiple social identities under a single account, it's easy for platform-specific code to leak into your business logic. For instance, consider a user who has both Facebook and Google+ identities. You might want to list the user's friends, as well as record their Widget purchases as app activities on Google+ or Open Graph objects on Facebook. The following code is one way to achieve those goals:


class User extends Model {

  public static User getCurrent() { ... }
  public Identity getSocialIdentity() { ... }

}

class UsersController extends Controller {

    public static void structuredShare(Widget widget) {
      Identity identity = User.getCurrent().getSocialIdentity();

      if (identity.getProvider().equals("facebook")) {
        // Share to Open Graph.
      } else if (identity.getProvider().equals("google")) {
        // Post app activity.
      }

      // Return response.
    }

    public static void listFriends() {
      Identity identity = User.getCurrent().getSocialIdentity();

      if (identity.getProvider().equals("facebook")) {
        // List the user's Facebook friends.
      } else if (identity.getProvider().equals("google")) {
        // List the people in the user's Google+ Circles.
      }

      // Return response.
    }

}

The code above works, but it will quickly get messy as you add more social features and integrate more identity providers. Ideally, you should be able to interact with your Users in the same way without worrying about their current Identity. A better approach would be to define the capabilities of a Provider and then create implementations for each social provider that you add. The following example demonstrates the concept:

public interface Provider {

  public void structuredShare(Widget widget);
  public List<User> getFriends();

}

public class GoogleProvider implements Provider {
  // Google logic.
}

public class FacebookProvider implements Provider {
  // Facebook logic.
}

class User extends Model {

  // ...
  public Identity getSocialIdentity() { ... }

  public Provider getProvider() {
    String provString = getSocialIdentity().getProvider();
    if (provString.equals("facebook")) {
      return new FacebookProvider(this);
    } else if (provString.equals("google")) {
      return new GoogleProvider(this);
    } else {
      throw new IllegalArgumentException("Invalid Provider");
    }
  }

}

class UsersController extends Controller {

  public static void structuredShare(Widget widget) {
    User.getCurrent().getProvider().structuredShare(widget);
    // Return response.
  }

  public static void listFriends() {
    List<User> friends = User.getCurrent().getProvider().listFriends();
    // Return response.
  }

}

Now your controller can focus on what you actually want to do on behalf of the user. Using the Provider pattern can save you a lot of code and make your current code more readable. If you add more identity providers to your app, your UsersController would remain exactly the same.

You can take this pattern one step further and put all of your authorization logic into Provider objects. For example, you could define a function provider.startAuthorization() that would intitialize the OAuth2 flow for the chosen provider with that provider's specfic options. The goal of this pattern is to let your business logic just use your User objects without knowing where they came from or how they operate.

Feature translation

After you have social sign-in from multiple providers, the next step is to create a consistent user experience regardless of the user's identity provider. The following information helps you translate the features of your Facebook integration to your Google+ integration, such as creating calendar events or incorporating the Google+ share button.

Sharing

If you are using Facebook's share widget, or the publish_actions permission with FB.api('/me/feed', ...), then you will want to use interactive posts for your users that are signed in with Google. Interactive posts have all of the sharing features you would expect, and much more.

To add an interactive post button to your page, you would add markup to your page with the special class g-interactivepost, such as the following example:

<button
    class="g-interactivepost"
    data-contenturl="https://plus.google.com/pages/"
    data-contentdeeplinkid="/pages"
    data-clientid="xxxxx.apps.googleusercontent.com"
    data-cookiepolicy="single_host_origin"
    data-prefilltext="Engage your users today, create a Google+ page for your business."
    data-calltoactionlabel="CREATE"
    data-calltoactionurl="http://plus.google.com/pages/create"
    data-calltoactiondeeplinkid="/pages/create">
    Tell your friends
</button>

Without any additional JavaScript, the code above instantly enables your users to share from your web app to Google+. Clicking the button displays a share dialog where the user can select circles to share with and customize the sharing text. The real magic is in the calltoaction, which adds a prominent call-to-action button to your post when it is seen in the Google+ stream. When someone clicks on the call to action button on an interactive post they are brought to the relevant page and can immediately take action. If a user clicks your interactive post on mobile and does not have the app installed, they are prompted to install it and then immediately deep-linked to a location in your app, which you define in the calltoactiondeeplinkid. Interactive posts can drive new users to your site, improve conversions, and increase engagement.

If you are looking for something even simpler, try the share button. Just add the following markup to the location on your page where you want the button to render:

<!-- Google+ Share Tag -->
<div class="g-plus" data-action="share"></div>

See the share documentation to see how you can customize the look, feel, and function to your needs.

If you are looking for a low-latency way to share without including any JavaScript, similar to Facebook's Share Dialog, you can use a share link. The share link is intended for native client applications, Flash applications, highly privacy-sensitive sites, and others who may not be able to use the +1 or share button. Adding the following markup to your site will include a simple icon which will pop open a share dialog for your visitors:

<!-- Replace {URL} with the URL of the page you want to share -->
<a href="https://plus.google.com/share?url={URL}" onclick="javascript:window.open(this.href,
  '', 'menubar=no,toolbar=no,resizable=yes,scrollbars=yes,height=600,width=600');return false;">
  <img src="https://www.gstatic.com/images/icons/gplus-64.png" alt="Share on Google+"/></a>

Structured data

If you publish to Facebook's Open Graph, you should also write app activities to Google. The following sample code demonstrates a simple use of the JavaScript API to write a review activity type:

var moment = {
    'type': 'http://schemas.google.com/ReviewActivity',
    'target': {
      'url': 'https://developers.google.com/+/web/snippet/examples/movie'
    },
    'result': {
        'type': 'http://schema.org/Movie',
        'name': 'Night of the Living Dead',
        'url': 'https://developers.google.com/+/web/snippet/examples/movie',
        'text': 'It is amazingly effective at whatever it is that it is supposed to do.',
        'reviewRating': {
          'type': 'http://schema.org/Rating',
          'ratingValue': '100',
          'bestRating': '100',
          'worstRating': '0'
        }
    }
  };

var request = gapi.client.request({
  'path': 'plus/v1/people/me/moments/vault',
  'method': 'POST',
  'body': JSON.stringify(moment)
});

request.execute(function(result) {
  console.log(result);
});

Make sure to update the data-requestvisibleactions attribute of your sign-in button to reflect the types of app activities that your application creates. For example, the following markup lets you post ReviewActivity and CommentActivity types:

<span
  class="g-signin"
  ...
  data-requestvisibleactions="http://schemas.google.com/ReviewActivity http://schemas.google.com/CommentActivity"
  ... >
</span>

An interactive post button can also serve as a sign-in button. If a user clicks an interactive post button before they are signed in, they will be shown the consent dialog and prompted to sign-in to your app. If you plan to display interactive post buttons to unauthenticated users, make sure to include data-scope and data-requestvisibleactions attributes with the same values as those on your sign-in button.

The example above shows a ReviewActivity, but there are many more other app activity types that you can use to share a variety of objects. While ReviewActivity requires a result object, some other activity types can be specified with just a type and a target url pointing to a page that is decorated with schema.org or Open Graph markup. If you already have Open Graph markup on your page from your Facebook integration, Google will automatically detect many of your app activity's properties. Use the Structured Data Testing Tool to preview how Google will display your page to the user.

You can also post app activities from your server using your chosen language's client library. See the moments.insert documentation for more information and sample code in a variety of languages.

Widgets

If you are using Facebook's social plugins, like the Follow button, you will be able to make use of the following Google+ platform plugins and features for the web.

Badge

If you are using Facebook's Like Box, add the Google+ Badge to your site. The Google+ Badge plugin is an easy way to link your page to your site, get more recommendations for your site in Google search, and grow your audience on Google+. Add the following code to your site:

<!-- Google+ Page Badge Tag -->
<div class="g-page" data-href="https://plus.google.com/{pageId}"></div>

See the Badge documentation to learn how to link to your personal profile, or to a Google+ Community.

Follow button

If your website includes the Facebook Follow button, you should use the Google+ Follow button. The follow button is a simple widget that works well in site designs that that use other social follow buttons or when space is constrained. The following code will include the button on your page:

<!-- Google+ Follow button tag -->
<!-- Replace {pageId} with the numeric ID or custom URL to your Google+ Page or profile
     Replace {relationshipType} with either publisher or author -->
<div class="g-follow" data-href="https://plus.google.com/{pageId}" data-rel="{relationshipType}"></div>

With the follow button, your users can immediately add your page or profile to their circles without leaving your site. To read more about customizing the button, read the follow button documentation.

+1 button

If your website has a Facebook Like button, use the Google +1 button. Include the following code on your page, and you're done:

<!-- Google+ +1 Tag -->
<div class="g-plusone" data-size="tall" ... ></div>

Read the +1 button documentation to learn how you can customize the +1 button experience on your page.

Content recommendations

The Google+ mobile content recommendations plugin are similar to Facebook's recommendation box, but are targeted to increasing mobile traffic and time spent on your site. Users will see recommended content based on +1s, shares, and recommendations from their circles.

To configure the content recommendations, you enable and customize the recommendations in your Google+ page dashboard, then add the following tag within your <head> tag on your pages that you want recommendations to display:

<link href="https://plus.google.com/{PAGE_ID}" rel="publisher" />

Calendar events

Creating calendar events is a great way to bring your users' interactions on your site into the real world. On Facebook you can create proprietary events using the FB.api("/me/events", ...) method. When you sign in with Google, you can harness the full power of Google Calendar to create calendar events for your users. First you will need to request the calendar scope when the user signs in, so modify your sign-in button to have the following attribute:

<span
  class="g-signin"
  ...
  data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/calendar"
  ... >
</span>

As you can see above, you can request additional scopes by declaring them as a space-delimited list. After you have the /auth/calendar scope, you can create events on the user's Google Calendar as shown in the following code:

<script>
  var event = {
    'summary': 'A new event!',
    'location': '123 My Street, Mountain View, CA',
    'start': {
      'dateTime': '<DATE STRING IN RFC3339 FORMAT>'
    },
    'end': {
      'dateTime': '<DATE STRING IN RFC3339 FORMAT>'
    }
  }

  var request = gapi.client.request({
    'path': '/calendar/v3/calendars/primary/events',
    'method': 'POST',
    'body': JSON.stringify(event)
  });

  request.execute(function(result) {
    console.log(result)
  });
</script>

This example creates an event in the user's primary Google Calendar. Consult the Google Calendar API documentation to see how to create recurring events, add other attendees, and create events from client libraries for other languages.

Deep links on the Google+ platform are the equivalent of linking to your native app on Facebook. When you create an interactive post, you can specify deep link information so that the user is directed to the correct view in your app or website on any platform. This example highlights the relevant attributes:

<button
  class="g-interactivepost"
  ...
  data-calltoactiondeeplinkid="/pages/create"
  data-contentdeeplinkid="/pages/create">
  ...
</button>

Interactive posts can deep link from both the content link and the call-to-action button. When the user clicks either the content link or the button, the identifier in the respective attribute is passed to your Android or iOS app, which your app would then intercept to determine the correct location within your app to launch. On Android and iOS, basic shared posts can also deep link into your app. For more infomation, see sharing with deep linking.

Deep links are more than just a pointer to your application, they are a way to attract new users and create a better user experience. If a user clicks your deep link on Android or iOS but does not have your application installed, they are automatically prompted to download the app and then taken to the correct screen once your app has been installed.

Next Steps

Now that you have integrated Google+ into your app, you can explore the features that are unique to the Google+ platform to create a great user experience.

Over-the-air installs

If you have a web app and a native Android app, you can use over-the-air (OTA) installs to drive users to your mobile app. After you publish in the Google Play Store and linked it to your app on the API console, change your sign-in button to have the data-apppackagename attribute:

<span
  class="g-signin"
  ...
  data-apppackagename="com.your.app.package.here"
  ... >
</span>

If your app meets the requirements for over-the-air installs, it automatically is enabled after you add the data-apppackagenamne attribute. When a user with a compatible Android device signs in to your web app, they are offered the option to install your app after they authorize your app. If they choose to install the app, it is automatically installed to their chosen app over the air.

Cross-platform single sign on

Cross-platform single sign on lets you stay connected to users and more easily keep them engaged across devices, removing the friction of consent and authentication. When a user signs in with Google on one device, they grant consent one time and can continue their experience seamlessly between web and Android apps. When users switch devices, Google+ Sign-In will automatically authenticate them, so they can be taken directly to the same state where they left off on the other device.

Cross-platform single sign on is easy to enable. In most cases, enabling this feature requires no changes to your code. See, see the enabling cross-platform SSO on Android or learn more about the feature to read more about Cross-Platform SSO.

Other Google APIs

When you use Google+ Sign-In, you get access to Google+ and additionally can have access to many other Google APIs. See the API Explorer for other APIs that you can access through the Google+ Sign-In flow. For example, you can request access to the user's Google Calendar, Google Drive, YouTube, and much more.

Sample app

The WigwamNow sample app for the web and for Android demonstrates all of the information presented above. Download both from the Google+ GitHub page to see how all of the material in this guide can be implemented in a production application.

Authentication required

You need to be signed in with Google+ to do that.

Signing you in...

Google Developers needs your permission to do that.