넷로그로 가기

초 남음

Developer / Documentation / Common issues when developing opensocial apps

Adding and reading parameters in the URL of notifications

Sometimes we want to reach an app from different places in the site, and we can indicate where we come from in the URL. Also, we often want to do user- or context-specific things with the user the moment he lands on the app. (for example if he gets their by clicking a notification 'you have a gift waiting for you!' sent out by the app).

We do this by passing along a parameter to the app page named appParams that contains a JSON string.

Adding view params to notifications sent from the openSocial app

Netlog.Message.Field.PARAMS is an "extension" that allows sending extra params in the URL of a notification, as follows:

 var recipients = [userId];
 var name = 'lol';
 var title = 'test'
 var params = {};
 params[opensocial.Message.Field.TYPE] = "notification";
 params[opensocial.Message.Field.TITLE] = title;
 params[Netlog.Message.Field.PARAMS] = { 'bagId' : bagId };
 var message = opensocial.newMessage('', params);
 opensocial.requestSendMessage(recipients, message);

(don't forget to <Require feature="netlog" /> on top of your app!)

These then end up in the notification, and when a user reaches an app trough this link, the app can retrieve these parameters as follows.

Note: if you are using the REST API you can also send these parameters along to show up in the notification link. They should be named params though.

Retrieving view-parameters

Within the openSocial app this type of URL-passed data will be available in gadgets.views.getParams()['key']

So if your URL is:
  • http://nl.netlog.com/apps/myApp?appParams={"foo":"bar!"}
  • ...and you run the function var myFooValue = gadgets.views.getParams()['foo']; in the openSocial app
  • ...then myFooValue will hold the string 'bar!'

NOTE: these have to be double quotes, single quotes in the JSON do not work.

For example this is done with the 'send as gift' button that can be clicked when sending a private message. This button takes you to the Gifts app, passing along the precise user + message so it gets pre-filled within the app.

 "appParams" => "{ "receiver" : "61507", "message" : "asdfasda%20%3A%20asdf%20asdf%20sadf%20asdf%20" }"

Installing a user skin from within an app

First of all, require the feature from Netlog in your app's moduleprefs section:

 <Require feature="netlog" />

You then have access to the following function:

 Netlog.Campaigns.loadSkin(distro, nickname, skinname);

That function will navigate to a 'preview' page where the user sees his profile with the new skin. The distro (this is how we call our language portals: EN, AR, FR,...) and the nickname should be requested via OpenSocial. The skinname will be provided to you by your contact at Netlog. Implementation example:

window.skinname = 'brands/mobstar_legends';
function loadSkin(responseData)
{
 var nickname = responseData.get('viewerData').getData().getField('nickname');
 var prefs = new gadgets.Prefs();
 var lang = prefs.getLang(); 
 //alert (' switching to skin: '+window.skinname);
 Netlog.Campaigns.loadSkin(lang, nickname, window.skinname);
}
function setProfileSkin()
{
//alert('setting profile skin...');
 var req = opensocial.newDataRequest();
 req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER), "viewerData");
req.send(loadSkin); 
}

I use cookies in my app and Safari won't let me do that from within an iframe.

This has to do with cross-domain security restrictions: Safari only accepts cookies from pages that the user explicitly 'navigated to'. Two possible workarounds exist:

  • Detect if the browser is safari, and if so show a big 'start app/game' link that the user has to click. Once the user clicked that, Safari trusts the site within the iframe enough to allow cookies. (e.g. Netlog game Dolumar does this)
  • Detect whether the cookie is there using JS, and if it isn't: create and POST a form to a next page (the POST makes safari trust it), set a cookie with that next page/script and then return to the original page that needs the cookie.

Stack Overflow has an interesting discussion on this issue.

I updated the XML spec code on my server, but I don't see the changes in the app

When testing your opensocial app within a Netlog app page, it may not seem to reflect your latest code changes. This is because we cache the XML spec file.

Add ?flushXML=1 to your app (or brand) page URL to disable caching of the XML spec file.

I try to send a notification trough OpenSocial PHP client but I get 500 - internal server error

Notifications within Netlog are a subtype of messages, so make sure you are doing calls to social/rest/messages and not to a social/rest/notifications endpoint.

Wrong:

 $batch->add($osapi->notifications->create($params), 'send_notification');
 $result = $batch->execute(); 
 
Correct:
$storage = new osapiFileStorage('/tmp/osapi');
 $provider = new osapiNetlogProvider();
 $provider->rpcEndpoint = null;
 $osapi = new osapi($provider, new osapiOAuth2Legged(self::KEY, self::SECRET, self::USERID));
 $batch = $osapi->newBatch();
 // Create a message
 $message = new osapiMessage(
 array(1, 2, 3), //recipients 
 'test message by osapi', //body
 'sent at ' . strftime('%X'), //title
 'NOTIFICATION' //type
 );
 $create_params = array(
 'userId' => $userId, 
 'groupId' => '@self', 
 'message' => $message
 );
 $batch->add($osapi->messages->create($create_params), 'createMessage');
 // Send the batch request.
 $result = $batch->execute();

In a game app, filtering friends for HAS_APP returns zero friends

This filtering returns only users that installed the app, but in the context of games you cannot 'install' apps, only play them on the gamepage. So this indeed never returns results. To keep track of who has already played your game, store this information on your end, or even better: use OpenSocial's to store any information you want.
So, concretely:

  1. For viewers entering your game to a point where you can consider them 'players' in any way, store a certain key-value pair in the persistant app storage.
  2. When you have the userid of the viewer and/or his friends, get the persistent storage for all of them and check whether the key from the previous step indeed corresponds with the value you set. If yes, they have 'installed' the game, if not they have never been in the game.

openSocial REST calls return a 501 Not Implemented error

Problem: I do a POST to something like

http://nl.api.netlog.com/opensocial/social/rest/people/57528694/@friends?st=NmQ4Yzc3NzMzNDIyYjViMmZhM2QzYmQ2ZmQ5OWQyMjA%3D&fields=nickname%2C+thumbnailUrl
... and I get a response saying 501 Not Implemented - You can't add people right now, even though I don't want to add anybody, just get information!

Explanation: our OpenSocial implementation prohibits certain types of actions, and before handling any incoming http request it detects those actions based on the request verb (GET, POST, PUT, etc). To fetch information, always use GET (or HEAD but this will rarely be needed). To insert or update information, use POST (or PUT, but again rather rare).

openSocial REST with the Security Token authentication method fails and gives a 401 status back.

Problem: I authenticated my external application using the security token generated in the gadget. However, when trying to load the user data from Netlog I get an 401 error back. For example:
Unexpected status code on get request (401), where the call was done to: http://de.api.netlog.com/opensocial/social/rest/people/@me/@self?format=xml&st=YmQxYzkyZDczMzA3ZWQ3ZDc1OTRlZmQwYzMyYTI3NmI%3D&fields=id%2Cage%2Cbirthday%2CthumbnailUrl%2Cbirthday%2Cgender%2Cnickname%2CdisplayName
 
->which doesn't look suspicious at all (it isn't) Solution: the security token expires after about 24 minutes. Consider pinging our server regularly in the background, i.e. do a new request every now and then to see if the security token still valid, and if not, get a new one. Alternatively, consider using for example the OpenSocial PHP client library with OAuth 2-legged, which will provide your app a more persistent authentication.

I want to load friends, but not all of them are returned

This can be caused by a number of different issues:

  • By default, only friends on the same distro are fetched, because apps are distro-specific (and friendships are not) so cross-language friends would cause weird errors in apps.
  • Check careful if you use any filtering that may not be appropriate (e.g. HAS_APP does not make sense for games)
  • Netlog only returns a maximum of 75 friends per call. However, you can always pass on a startIndex parameter. So if you really need to fetch all friends, consider writing some sort of while loop that does calls with increasing start index until no more friends are returned. (see below)

    Chances are however, that a faster and more elegant solution will be to use a pager of some sorts. We also have a search friends extension that may be worth looking into.

In PHP with the openSocial PHP library for example, if you have a method getViewerFriends($countPerFetch, $index), something like the following would fetch all viewer friends, by repeatedly fetching friends until no more are returned (or $maxIterations is reached).

public function getAllViewerFriends()
{
 $count = 1;
 $index = 0;
 $countPerFetch = 50;
 $allFriends = $this->getViewerFriends($countPerFetch, $index);
 $lastCount = count($allFriends);
 $this->debug("Last count: $lastCount ...");
 $currentIteration = 0;
 $maxIterations = 3;
 while ($lastCount >= $countPerFetch)
 {
 if ($currentIteration >= $maxIterations)
 {
 $this->debug("Reached max of $maxIterations iterations! Stopping loop...");
 break; 
 }
 $index += $countPerFetch;
 $currentBatch = $this->getViewerFriends($countPerFetch, $index);
 $allFriends = array_merge($allFriends, $currentBatch);
 $currentIteration ++; //could connect this to index and vice versa 
 $lastCount = count($currentBatch);
 $this->debug("Last count: $lastCount ...");
 }
 return $allFriends;
}

requestShareApp does not work in the sandbox

Apps can have a page (i.e. be accessible on different) on some, any or all Netlog distros (nl, en, ar ...). We have a policy that you can only share an app with friends that are on a distro that also has a 'page' of this app. (this is not necessarily the case because we allow cross-language friends)

Now, the way our sandbox works is that it simulates an app page on a 'hidden' developer Netlog distribution (dev.netlog.com if you will), independent on whether you access it from NL.netlog.com, EN.netlog.com... What this means is that none of your friends will be on the 'correct' distro to view this app, and that is why requestShareApp will not accept any friends from the Sandbox. It will behave as expected once you start testing your app from a page - within - Netlog though (we can set you up to do that).

I try to use gadgets.views.getParams() but it is not working

This is probably because you forgot to add <Require feature="views" /> in your spec XML.

I use OpenSocial REST to post activity logs, but special characters are not coming trough properly.

This problem can be traced back to json_encode() behaving weirdly when it comes to unicode characters. It can be circumvented by using the helper function described in the activities section described here.

I want to change the height of my gadget

You can set the height of your gadget with the OpenSocial JS function gadgets.window.adjustHeight();. You can provide the height in px as argument to this function, or nothing at all in which case it will be resized according to its contents.

Important: the adjustHeight() function will only work if you include the dynamic-height feature in your spec XML like this:

<Require feature="dynamic-height" />
 

You would typically call this function after your gadget is fully loaded. The function gadgets.util.registerOnLoadHandler(myStartFunction) can play an important part in that.

One more remark: often, if you use this function but find that your gadget is not properly resizing, it is because you have JavaScript errors. Install FireBug or a similar browser debugging tool to see what is going wrong.

I want to ask the user to become friend with my brand or take over its skin.

Our extension Netlog.Campaigns.dialogRequest() for the OpenSocial JS API allows you to show a dialog to the user, asking if he wants to become friends with your brand, or take over its skin. You can pass along a callback function that will be called after the dialog is closed, and this function will receive a status (e.g. 'ACCEPTED') as first argument based on which option the user chose.

In order for this function call to work you need to <Require feature="netlog" />.

Example code (including function arguments) for the become brand friend dialog:

 function onBecomeFriendButtonClicked()
 {
 alert("Will request to become friend .!."); 
 var myCallback = function(data){
 debug("RECEIVED CALLBACK:");
 debug(data);
 if (data.success)
 {
 alert("succesfully changed friendship!"); 
 }
 else
 {
 alert("Skinfriendship not accepted succesfully"); 
 }
 };
 Netlog.Campaigns.dialogRequest({'requestedAction' : 'becomefriend', 'message' : 'become friends with my brand page now AND WIN A PRIZE!!', 'callback' : myCallback});
 }

Example code (including function arguments) for the set brand skin dialog:

 function onSetSkinButtonClicked()
 {
 var skinname = 'brands/fa_glamour_user';
 alert("Will requests to set skin:" + skinname + '!!!'); 
 var myCallback = function(data){
 debug("RECEIVED CALLBACK:");
 debug(data);
 if (data.success)
 {
 alert("Skin succesfully changed!"); 
 }
 else
 {
 alert("Skin not changed succesfully"); 
 }
 };
 Netlog.Campaigns.dialogRequest({'requestedAction' : 'setskin', 'skinname' : skinname, 'message' : 'Je gaat nu de skin installeren EN WIN EEN PRIJS!', 'callback' : myCallback}); 
 }