iGoogle (Deprecated)

Removing social functionality from iGoogle gadgets

Important: iGoogle will be retired on November 1, 2013. We are no longer accepting new gadget submissions, but you can still update your previously submitted gadgets.

Overview

iGoogle’s gadget platform added support for social interactions several years ago. The web has evolved a lot since then, and we recently announced open signups for Google+, our new product for bringing real-life sharing to the web. As indicated in our blog post, we’ll be removing iGoogle’s social features on January 15, 2012. Therefore, you will need to remove any use of social features in your gadgets. This document walks through the process, including ways to re-implement some features in other ways.

If you’re interested in developing new social applications and games that use Google+, please keep an eye on our Google+ Platform Blog.

Determine whether you need to make any changes

If your gadget spec has the following elements as a child of the ModulePrefs element, you will need to tweak your code to remove legacy social API calls.

<Require feature="opensocial-0.x" />
<Require feature="osapi" />

Otherwise, you don’t need to make any changes.

What will be removed from the iGoogle platform?

Everything under the opensocial.* and osapi.* namespace will be removed, so you will need to make sure that there are no such references in your gadget by removing or rewriting any code block containing an opensocial.*/osapi.* object or function. To test your gadget with the legacy social APIs disabled, run iGoogle with noos=1 added as a URL parameter: http://www.google.com/ig?noos=1

If your application preserves any data in AppData storage, you need to migrate that data to somewhere else, such as hidden UserPrefs or an external server. Otherwise, your data will be lost. In the next section, we’ll show you how to migrate AppData.

AppData migration example

Let’s say you have a quiz gadget which stores users’ scores in AppData storage, so you need to re-write the code. This section will walk you through the process of migrating that data into a hidden UserPrefs. This method is very easy to implement, but please note that the actual migration will be performed only when the user opens your gadget. Additionally, UserPrefs has a 1.5 KB limit on its storage size, so if the size of your data exceeds this limit, you cannot move your data to hidden UserPrefs -- instead, use an external server.

Phase 1

  • Step 1: Remove social features from the gadgets.
  • Step 2: Add 2 hidden UserPrefs.
    • appDataMigrated (default = false)
    • <UserPref name="appDataMigrated" datatype="hidden" default_value="false"/>
    • userScore
    • <UserPref name="userScore" datatype="hidden" default_value="0"/>
  • Step 3: Add data migration functions and change your init() function to call it (example code below).
  • Step 4: Change the thumbnail preview and description of the gadget, if applicable (removing the social icons or description mentioning social features).

Phase 2

  • Step 5: Remove <Require feature="opensocial-0.x"/> once you are sure that your regular users have visited the gadget and their application data has been migrated.
  • Step 6: Remove the migration code and the hidden UserPref (i.e. appDataMigrated).

Sample migration code/functions used in the step 3 above.

Modify init() function to call the migration function.

/**
 * Init function of the gadget
 **/
function init() {
  // if the gadget is using social features and this particular user’s
  // data has not been migrated then invoke the migration function;
  // otherwise render the gadget normally
  if (gadgets.util.hasFeature('opensocial-0.8') &&
      !prefs.getBool('appDataMigrated')) {
    // Invoke the migration function only once.
    migrateAppData();
  } else {
     loadHomeView();
  }
}

Define the migration function.

/**
 * This function fetches the user data from the AppData storage and then invokes the
 * callback function appDataReceived which will store the data into the new userprefs or
 * App Engine
 **/
function migrateAppData() {
  var req = opensocial.newDataRequest();
  var idSpecOwner = opensocial.newIdSpec({ 'userId' : 'OWNER',
    'groupId' : 'SELF' });
  req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.OWNER, {}),
    'owner');
  //Fetching owners data
  req.add(req.newFetchPersonAppDataRequest(idSpecOwner, '*'), 'owner_data');
  req.send(appDataReceived);
}

(Option 1) Use following function if the data should be migrated to userprefs. In this example we're copying data stored as 'score'.

/**
 * This is a callback function responsible for moving data into userprefs.
 * (if the size of your data in AppData exceeds the 1.5 KB limit you cannot rely on this
 * migration method; see option 2 below)
**/
function appDataReceived(dataResponse) {
  // Check the response
  if (dataResponse && dataResponse.get('owner')){
    owner = dataResponse.get('owner').getData();
    owner_data = dataResponse.get('owner_data').getData();
    // Check if data exists for migration to userpref.
    if (!isEmptyObj(owner_data)) {
      owner_data = owner_data[owner.getId()];
      if (owner_data && owner_data['score']) {
        user_score = owner_data['score'];
        // Migrate data to user prefs
        prefs.set('userScore', user_score);
      }
    }
    // Set appDataMigrated to true since the data has been migrated now.
    prefs.set('appDataMigrated', 'true');
  }
  // Migration is done; now load the home view of the gadget
  loadHomeView();
}

(Option 2) Use following function if the data should be migrated to an external server

If the total size of your data exceeds 1.5 KB, you should not use UserPrefs for storing that data, so you will need an external server-side application for storage. In this example, we will use the same gadget as in the prior code snippets.

/**
 * This is a callback function responsible for storing the data into your external
 * server-side storage application.
**/
function appDataReceived(dataResponse) {
  // Check the response
  if (dataResponse && dataResponse.get('owner')){
    owner = dataResponse.get('owner').getData();
    owner_data = dataResponse.get('owner_data').getData();
    // Check if data exists for migration to userpref.
    if (!isEmptyObj(owner_data)) {
      owner_data = owner_data[owner.getId()];
      if (owner_data && owner_data['score']) {
        user_score = owner_data['score'];
        // Migrate data to an external server
        migrateDataToServer(user_score, owner.getId(), callbackFunc)
      }
    }
  }
  // Migration is done; now load the home view of the gadget
  loadHomeView();
}

function migrateDataToServer(score, userId, callback) {
  # First, create a post payload.
  var postStr = [];
  postStr.push('score=' + encodeURIComponent(score));
  postStr.push('user_id=' + encodeURIComponent(userId));
  postStr = postStr.join('&');
  # Second, create parameters for a Signed request. It will enable the backend server
  # to determine whether the request is coming from the correct gadget or not.
  var params = {};
  params[gadgets.io.RequestParameters.CONTENT_TYPE] =
    gadgets.io.ContentType.JSON;
  params[gadgets.io.RequestParameters.AUTHORIZATION] =
    gadgets.io.AuthorizationType.SIGNED;
  params[gadgets.io.RequestParameters.POST_DATA] = postStr;
  params[gadgets.io.RequestParameters.METHOD]= gadgets.io.MethodType.POST;
  params['OAUTH_SERVICE_NAME'] = 'HMAC';
  # Send the score to the backend server.
  gadgets.io.makeRequest(APPURL + '/updatescore',
    function (data) {
      if(data.error) {
        handleError('errorid=' + data.error.errorId);
       } else {
        prefs.set('appDataMigrated', 'true');
        // Continue with the rest of the processing.
      }
    }, params);
}

Authentication required

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

Signing you in...

Google Developers needs your permission to do that.