ptg
74
Chapter 5 Communication and Viral Features
// Update the UI for the failures
for(var i = 0; i < failure.length; i++){
clicked = current_list.list_dom["myspace.com:" + failure[i]];
if(clicked) clicked.style.backgroundColor = "red";
}
}
}
}
So, there is a lot going on here.The callback for
requestShareApp
is especially
important.The first thing that really happens is that the various types of errors are
trapped, and an error message is displayed if one is found.
If there was no error, we cycle through the list of currently selected users, revert the
background of the corresponding div tags to white, and reset the list.There are now two
possibilities: the user either canceled the pop-up or hit Send. If the pop-up was canceled,
there’s no more work to do. If the pop-up wasn’t canceled, the user must have hit the Send
button, so we need to figure out who the actual recipients were.We do this by accessing the
responseValues
object in the
ResponseItem
that’s passed back to us.
responseValues
contains two arrays: One,
success
, contains the list of users who were successfully sent an
invite.The other,
failure
, contains the list of users who had an error occur when the
invite was sent. Both arrays contain the integer IDs of the specified users.
There are a couple of things to note when accessing the success and failure arrays.
First, users who already have the app installed won’t get the invite, but neither will they
show up in either array. Second, the IDs in the array are integers, so they don’t exactly
match the IDs that are sent by the API (in the format
"myspace.com:6221"
).
Back to the function at hand.We extract the
success
and
failure
arrays and loop
through them.We turn the background color of all the successful recipients to green,
and that of all the failures to red.You’ll notice that we have to append
"myspace.com
:
"
to the beginning of each ID so it matches up with the IDs we fetched from the API.
It may be useful to add a More button to your app, something like “Select Random
20” that will randomly select 20 of the user’s friends.This will help encourage users to
share the app with a larger group of friends; turning 20 clicks into one click makes it
much easier for your users.
Using opensocial.requestSendMessage to Send
Messages and Communications
Let’s examine how
opensocial.requestSendMessage
works.The
requestSendMessage
function provides a number of ways for apps to communicate with users.
MySpace supports the following message types:
n
Send Message: a private one-to-one message that will arrive in the user’s Mail
Center in-box
n
Comment: a public one-to-one message that will appear on the user’s Profile
page in the Comments section
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
n
Bulletin: a one-to-many message that will appear in the Bulletins module of each
of the user’s friends’ Home pages
n
Blog: a one-to-many message that will appear on a MySpace user’s Blog
n
Profile: not a message per se; allows an app to edit/update the user’s Profile.The
following Profile sections can be edited and are chosen by the user in a drop-
down menu:
About Me
I’d Like to Meet
Interests
Edit Artist Profile
Movies
Television
Books
Heroes
Defining requestSendMessage
opensocial.requestSendMessage
has the following signature:
opensocial.requestSendMessage =
function(recipients, message, opt_callback, opt_params)
You probably noticed that the signature for
opensocial.requestSendMessage
is
very similar to that of
opensocial.requestShareApp
.The big difference is that you’re
allowed to define only one recipient ID at a time; the container will reject an array of
IDs. Similar to
requestShareApp
, however, are
opt_callback
, which is the function
that’s invoked when the pop-up modal has closed, and
opt_params
, which is unused.
Note
Some targets don’t require a recipient; these are Bulletin, Profile, and Blog. Any
recipient
value passed in for these targets will be ignored.
The
message
parameter is an object of type
opensocial.Message
.The supported
content of the message depends on the message type; here’s a quick breakdown:
n
Types that support a message title are Send Message, Comment, Bulletin, and Blog.
The title doesn’t support any HTML markup.
n
All of the message types support a message body. All support some HTML markup
in the body.Tags like <div>, <script>, and <span> are stripped out, but tags like
<a>, <img>, <b>, and <em> are allowed.
When creating the
opensocial.Message
object, you need to specify the
opensocial.Message.Field.Type
property; this specifies which of the message types
Using opensocial.requestSendMessage to Send Messages and Communications
75
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
will be sent.Table 5.1 shows the list of supported types and the
opensocial.Message.
Field.Type
fields to which they correspond.
Profile and Blog are MySpace-specific extensions and not in the OpenSocial spec,
which is why they’re namespaced a little differently. In the code that follows, we’ll show
you how to make use of the message types when using
requestSendMessage
.
Writing the requestSendMessage Code
Now that we’ve defined our
requestSendMessage
function, let’s plug it into our Tic-Tac-
Toe app and try it out.The following example function wraps
requestSendMessage
and is
useful if you want to use
requestSendMessage
in multiple places throughout your app:
function rsmWrapper(id, subject, body, type, callback){
var param = {};
param[opensocial.Message.Field.TYPE] = type;
param[opensocial.Message.Field.TITLE] = subject;
var message = opensocial.newMessage(body, param);
opensocial.requestSendMessage(id, message, callback);
}
Note that the function is fairly similar to the
requestShareApp
wrapper.This
function just requires two additional parameters to construct the
opensocial.Message
object:
subject
and
type
.The
type
parameter corresponds to one of the
opensocial.Message.Field.Type
values found in Table 5.1.
Now that we have our
requestSendMessage
wrapper, we can make use of it in the
app by creating different types of messages.A fairly simple and effective type of message
is a bulletin; it is a one-to-many message that gets blasted out to all the user’s friends.
function rsmBulletin(){
var this_app = opensocial.getEnvironment().currentApplication;
var profile_link =
this_app.getField(MyOpenSpace.Application.Field.PROFILE_URL);
var image_link =
this_app.getField(MyOpenSpace.Application.Field.ICON_LARGE);
76
Chapter 5 Communication and Viral Features
Table 5.1 Supported Message Types
Message Type Value of opensocial.Message.Field.Type
Send Message opensocial.Message.Type.PRIVATE_MESSAGE
Comment opensocial.Message.Type.PUBLIC_MESSAGE
Bulletin opensocial.Message.Type.NOTIFICATION
Blog MyOpenSpace.PostTo.Targets.BLOG
Profile MyOpenSpace.PostTo.Targets.PROFILE
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
var subject = "Social Tic-Tac-Toe is Here!";
var body = "Hey everyone! I' m playing TTT online with my friends, come";
body += "<a href='" + profile_link + "'>play a game</a> with me!";
body += "<center><img src='" + image_link + "'/></center>";
rsmWrapper(opensocial.IdSpec.PersonId.VIEWER, subject, body,
opensocial.Message.Type.NOTIFICATION, rsmBulletinCallback);
}
Since bulletins don’t use any template messaging, we have to generate all the links
ourselves.To do this, we make use of the instance of a
MyOpenSpace.Application
object for this app.When an app is rendered, the MySpace platform pushes down a
script-accessible representation of the app’s information.This object may be accessed
from the environment with the call
opensocial.getEnvironment().currentApplication
Specific data that may be found in this object includes:
1. App ID, accessed via the field enum
MyOpenSpace.Application.Field.ID
2. Name, accessed via the field enum
MyOpenSpace.Application.Field.Name
3. Profile URL, accessed via the field enum
MyOpenSpace.Application.Field.
PROFILE_URL
4. Install URL, which for right now is the same as the Profile URL (which is where
the app is installed from), accessed via the field enum
MyOpenSpace.
Application.Field.INSTALL_URL
5. Canvas URL, accessed via the field enum
MyOpenSpace.Application.
Field.CANVAS_URL
6. The 64ϫ64 icon URL, accessed via the field enum
MyOpenSpace.Application.
Field.ICON_LARGE
7. The 16ϫ16 icon URL, accessed via the field enum
MyOpenSpace.Application.
Field.ICON_SMALL
The
Application
object behaves just like the
Person
object—data is accessed
through the
getField
function. For example, to access the app’s name in your script
code, you would make the following call:
opensocial.getEnvironment().currentApplication.getField(
MyOpenSpace.Application.Field.NAME);
Here we use the app’s Profile URL and the large icon to generate the bulletin mes-
sage. Some of the supported HTML tags are also used for the body.Then the wrapper
function is called and voilà! We’ve sent our first message!
Bulletins are great for getting the word out to a large audience, but they lack a per-
sonal touch. In our Tic-Tac-Toe app, one user can challenge another user to a game.
Using opensocial.requestSendMessage to Send Messages and Communications
77
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
When this challenge is initiated, we send out a message from the challenger to the
challenged.The code for that looks like this:
function rsmMessage(){
var current_list = TTT.Lists.getCurrentList();
var id = this.list_index;
TTT.Lists.itemClicked = id;
var this_app = opensocial.getEnvironment().currentApplication;
var profile_link =
this_app.getField(MyOpenSpace.Application.Field.PROFILE_URL);
var image_link =
this_app.getField(MyOpenSpace.Application.Field.ICON_LARGE);
var subject = "I challenge you to a TTT duel!";
var name = "";
for(var i = 0; i < current_list.list.length; i++){
if(current_list.list[i].getId() == id){
name = current_list.list[i].getDisplayName();
break;
}
}
// If the name isn't empty, add a space before the name
name = ("" === name) ? name : " " + name;
var body = "Hey" + name + "! You've been challenged to ";
body += "a game of Tic-Tac-Toe, click <a href='" + profile_link + "'>";
body += "here</a> to accept the challenge!<center>";
body += "<img src='" + image_link + "' /></center>";
rsmWrapper(id, subject, body,
opensocial.Message.Type.PRIVATE_MESSAGE, rsmMessageCallback);
}
This code is fairly similar to the bulletins code.We use the
MyOpenSpace.
Application
object to generate a message and then invoke the wrapper.There is also
some app-specific code in this function that determines the ID and name of the
challenged user; this ID is sent into the wrapper while the name is used to personalize the
message. Adding a person’s name to a message is an old trick that helps the message seem
a little less like a form letter.
Callback in requestSendMessage
The callback for
requestSendMessage
works the same as
requestShareApp
. An error
could be generated before the modal dialog is shown; otherwise the value 1, 0, or Ϫ1 is
returned.
78
Chapter 5 Communication and Viral Features
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Let’s take a look at one quick example:
function rsmMessageCallback(response){
var div = TTT.Tabs.getCurrentContainer().firstChild;
if(response && !response.hadError()){
if(0 === response.getData()){
div.innerHTML += "challenge cancelled...";
}
else if(1 === response.getData()){
div.innerHTML = "challenge sent!";
}
}
else{
log("Oops, there was an error, try refreshing the page!");
}
}
First we check for an error. If one was found, we display an error message asking the
user to refresh the page.
Most errors that occur with the messaging system are intermittent and can be fixed with
a refresh. If there was no error, a simple message is displayed reaffirming the user’s action.
Getting Your App Listed on the Friend Updates with
opensocial.requestCreateActivity Basics
On every user’s MySpace Home page there is a module that displays the user’s Friend
Updates.These updates are a feed and might include information like “John added a new
photo,”“Mary and John are now friends,” or “Susan installed the Tic-Tac-Toe
application.”These updates are ordered by date, and the newest information is always
displayed on top.
When an app creates an activity, the activity appears in this feed.That makes any app
activity a one-to-many message that will appear in the Friend Updates feed for each of
the user’s friends.With activities, applications can define numerous custom messages that
will appear in a user’s Friend Updates.
Activities can be created only from the app’s Canvas surface, but they’re a great way to
embed your app into a user’s MySpace experience and promote your application at the
same time.
Defining opensocial.requestCreateActivity
opensocial.requestCreateActivity
has the following signature:
opensocial.requestCreateActivity = function(activity, priority, opt_callback)
This means it’s a function that must include an activity (
opensocial.Activity
), a
priority (
opensocial.CreateActivityPriority
) setting for the request, and
opt_callback
as the function to call once the request has been processed.
Getting Your App Listed on the Friend Updates
79
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Note
At the time of this writing,
opensocial.CreateActivityPriority
is not being checked
or used by MySpace. You’ll notice in the code that follows that we always pass in a value
of high (
opensocial.CreateActivityPriority.HIGH
) as opposed to low
(
opensocial.CreateActivityPriority.LOW
).
If you have
opensocial.CreateActivityPriority
in your code and MySpace starts
making use of it, the behavior of your app may be affected, so it’s good to keep this in
mind should your app suddenly start doing something.
Let’s take a quick look at how OpenSocial defines the priorities:
High: If the activity is of high importance, it is created even if this requires asking
the user for permission.This might cause the container to open a user flow that navi-
gates away from your gadget.
Low: If the activity is of low importance, it is not created if the user has not given
permission for the current app to create activities.With this priority, the
requestCreateActivity
call never opens a user flow.
Using the Template System to Create Activities
One of the most important elements of creating and raising activities is the template
system. In fact, it’s so important that it needs to be explained before we start looking at
code. Unlike messages, which are completely defined and passed into the function as
static text, activities make use of a custom template system. Basically, you create a
template for your activities’ messages and the variables are resolved at runtime.Templates
must be used for activities. Every template must have a title containing up to a
maximum of 160 visible characters. Each template may also optionally specify a body
having up to 260 visible characters.
Your message template is based on a text string with some optional variables (which
you may occasionally hear referred to as “tokens”) thrown in.These variables are
replaced by real data once the activity is raised. A basic activity’s message might look
something like this:
"Susan installed Tic-Tac-Toe on: ${date}."
When the template is run, you’ll specify that
${date}
will be replaced with a string
containing the current date and time. So, if you give the variable
${date}
a value like
“September 28, 2010,” the resulting message would read
“Susan installed Tic-Tac-Toe on: September 28, 2010.”
Data Types
In our first example, the
${date}
variable was a string. However, you can also specify
the data type of a variable.The two currently available data types are Literal and Person.
80
Chapter 5 Communication and Viral Features
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
A Literal data type, used in our first date example, is any string.Your variable is then
simply replaced by that straightforward string.
A Person data type is slightly more complex. If a variable is defined as a Person data
type, the variable is then replaced by a person’s display name and a link to the person’s
Profile when it appears in the feed.
For example, let’s say we have a template where the variable
${opponent}
is of type
Person. It might look like this:
"You've been bested at Tic-Tac-Toe by ${opponent}."
To get this template message to display correctly, you need to pass in the opponent’s
user ID. For example, if we pass in the string
"6221"
(Tom’s ID) for our
${opponent}
variable, our message would read
“You’ve been bested at Tic-Tac-Toe by Tom.”
The word To m would then link to Tom’s Profile.
Reserved Variable Names
There are a number of variables that are reserved (see Table 5.2), but the most interesting
one is
${sender}
. This is because
${sender}
is actually a required variable in your
template title, meaning you’ll be using it a lot.
The variable
${sender}
is a Person-type variable, which means it’s replaced by the
Viewer’s name and Profile link. For example, let’s say we changed our template to read
"${sender} raised this event, making ${sender} the Viewer!"
If Susan were to raise an event with that variable, the resulting message would read
“Susan raised this event, making Susan the Viewer!”
Getting Your App Listed on the Friend Updates
81
Table 5.2 Reserved Variable Names
Reserved Variable Name Use
${subject}
Replaced with a link to the Viewer’s Profile
and the Viewer’s display name as the
corresponding text
${subject.DisplayName}
Replaced by the Viewer’s display name
(no link)
${subject.Id}
Replaced by the Viewer’s ID
${subject.ProfileUrl}
Replaced by the Viewer’s Profile URL
${canvasUrl}
Replaced by the app’s Canvas URL
${variable_name.Count}
Used when variables are aggregated and
where
variable_name
is the name of a
variable used in the template
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
But if her arch-nemesis,Tom, raised the event, the message would read
“Tom raised this event, making Tom the Viewer!”
In each instance the Viewer’s information is used for the
${sender}
variable.
Aggregation
When a user has a large number of applications, and friends who like applications, the
user’s feeds can get crowded with information and updates. Because of this, activity feeds
are aggregated. If a user has five friends all playing Tic-Tac-Toe and raising activities for
the app, all of those activities are aggregated into a single feed entry for Tic-Tac-Toe.
For example, let’s create a new message template and see what would happen when
it’s raised multiple times. Let’s start with a new template:
"${sender} is playing Tic-Tac-Toe with ${opponent}."
In this example we’d want to aggregate the
${opponent}
variable (you can learn
how to specify aggregated variables by skipping ahead to the section on using the
Template Editor). The first time I raise the event, my opponent’s ID is
"6221"
(Tom,
again!).The resulting message reads
“Susan is playing Tic-Tac-Toe with Tom.”
If Susan raises the event again, this time challenging her friend Matt to a game, the
resulting message reads
“Susan is playing Tic-Tac-Toe with Tom and Matt.”
And if Susan raises the event a third time, but this time challenging Tila Tequila to a
battle of Tic-Tac-Toe, the resulting message would read
“Susan is playing Tic-Tac-Toe with Tom, Matt, and Tila!”
Now that’s a game I would like to see. Notice that not only does the templating sys-
tem keep aggregating your message feeds, it also makes them grammatically correct by
adding commas and the word and.
Body and Media Items
We have variables and data types, but there’s more to a message template than that.
What about pictures and the message itself? That’s where body and media items come
into play.
The body is similar to a template’s title, but it’s optional and can hold more charac-
ters. If you include a body, it displays on the second line under your specified title.
82
Chapter 5 Communication and Viral Features
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Media items can be any picture on MySpace that’s accessible to the Viewer. In
Chapter 3, Getting Additional MySpace Data, we fetched a list of the Viewer’s photos,
displayed them on the page, and allowed the player to select one for a custom board back-
ground. If a custom background is selected, it is used as a media item in any raised activity.
You’re allowed to include a maximum of three media items in a message template. All
will be rendered on the second line of the message.
Using the Template Editor to Create Templates
Now that you know how templates work, you’re ready to create some new templates for
your app.To do this, you’ll use the Template Editor tool found on your My Apps page.
Under each application there is a tool entitled Templates (Figure 5.6); click it to be taken
to your Templates page (shown in Figure 5.7).
Click on Create Template to create new templates for your app.This will take you to
the template creation screen.
From this screen (Figure 5.8) you can edit existing templates or create a new one.
Let’s look at an existing template for our Tic-Tac-Toe application.
Getting Your App Listed on the Friend Updates
83
Figure 5.6
Screen shot of My Apps S Templates link
Figure 5.7
Screen shot of an existing Templates list
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
On the individual Template screen, you can see all of the pertinent template informa-
tion. Under Content you’ll find the template’s name and unique identifier along with
the title and the body.There are also separate tabs for Single Form instances (when just
one activity is raised) and Aggregate Form instances (multiple activities are raised).
Under Variables, you can add and specify data types and even test values for each of
your variables. Below this section are sample media items that you can use to test how
they’ll appear when you preview or run your template.
To test your template, click the Preview Template button.This creates a preview of
your template in the bottom portion of the screen using the test data you indicated
under Variables and Media Items.
You’ll also be provided with sample JavaScript code that can be used to raise the
event.You can actually just cut and paste this code into your app to begin raising activi-
ties, but you’ll most likely want to customize it (see “Raising the Event” in the follow-
ing section).
If you’re satisfied with your template, click the Save Template button to save your
template for later use.
Once your template is saved, you can switch it from development status to live status.
To do this:
1. Go back to your Templates page.
2. Click the Publish button next to the template you want to make live.
3. Click OK when prompted.
From your Templates page you can also delete or edit an existing template.
84
Chapter 5 Communication and Viral Features
Figure 5.8
Screen shot of the Templates screen
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Using opensocial.requestCreateActivity
Now that we understand what
opensocial.requestCreateActivity
looks like and
how to construct a template, let’s actually use the function.
Raising the Event
The template we’re using for our activity is the following:
${subject} has started a game of
<a href='${canvasUrl}&appParams=${params}'>Tic-Tac-Toe</a>
against ${opponent}
We’re doing something a bit tricky with the
href
attribute in the anchor tag.This
actually allows us to send custom parameters into the Canvas surface of the app if the link
is clicked.This can be especially useful for tracking purposes.You can try different mes-
sages, each with a different
${params}
value, and see which one is clicked more often.
The actual code to raise the event looks like the following:
function raiseActivity(){
// Create the parameters
var param = {};
// Required template name
param[opensocial.Activity.Field.TITLE_ID] = "x_and_y_started_game";
// The actual parameter values
param[opensocial.Activity.Field.TEMPLATE_PARAMS] = {
"opponent" : currentGame.opponentId,
"params" : "{\"from\":\"act\"}"
};
// Check if a custom background is set to use for
// a media item
if(currentGame.customBG.usingCustomBG()){
// Get the photo object
var photo = currentGame.customBG.photo;
// Parse out the URI
var uri = photo.getField(MyOpenSpace.Photo.Field.PHOTO_URI);
// Create the opensocial.MediaItem object
var media_item = opensocial.newMediaItem("image/jpeg", uri)
// Stick it in an array
var media_item_array = [ media_item ];
// Insert the array into the parameters
param[opensocial.Activity.Field.MEDIA_ITEMS] = media_item_array;
}
Getting Your App Listed on the Friend Updates
85
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
// Create the opensocial.Activity object
var activity = opensocial.newActivity(param);
// Raise the activity!
opensocial.requestCreateActivity(activity,
opensocial.CreateActivityPriority.HIGH, raiseActivityCallback);
}
First, the activity template is defined as
"x_and_y_started_game"
.This is the
unique identifier for the desired template and can be found in the Template Editor
under Template Name.
The template variables are then given actual values; the
${opponent}
variable is
assigned the value of the ID of the opponent, and the
${params}
variable is assigned a
JSON object.This is an example of how you might use different template messages for
tracking purposes, since here we’re saying the user got to the Canvas page from an activ-
ity. Meanwhile, the two variables correspond to the list of variables in the Template
Editor under Variables.
The next block of code attaches a media item to the activity. A couple of things to
note here: First, the media item URI must conform to an API-style URI and not a reg-
ular old URL, such as www.example.com/my_picture.jpg.The best way to get these API
URIs is through the API itself, as we do here in the app.
In our code we fetch the list of photos for a user and save those values into a list.
When a photo is selected, we match it to the correct entry in the list and parse out the
URI.This URI is accessed from the
MyOpenSpace.Photo
object using the
MyOpenSpace.Photo.Field.PHOTO_URI
.
The second thing to note is that an activity requires an array of media items. So, even
if you have only one media item, make sure to stick it in an array.
Once all the parameters are set up, the
opensocial.Activity
object is created and
it’s passed into
requestCreateActivity
.
Note
What are we doing there with the custom parameters in the template? Well, custom values can
be passed into an app’s Canvas surface by appending an
"appParams"
key to the query string.
So, for example, by appending
&appParams={"hello"%3A"goodbye"%2C"from"%3A"act"}
to the end of the Canvas URL, we pass the JSON object
{ "hello" : "goodbye", "from" :
"act" }
into the app.
These values can be picked up inside the Canvas by doing the following:
gadgets.views.getParams().hello;
gadgets.views.getParams().from;
In this case, the first line resolves to "goodbye" and the second to "act".
86
Chapter 5 Communication and Viral Features
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Using Activity Callbacks to Combat Permission-Denied Errors
Uh-oh! Permission denied? It turns out that a separate permission is required to raise an
activity for a user. If this permission isn’t set, the container blocks the request and returns
an error. So that’s that, I guess. Oh well, better luck next time…
Not necessarily;
opensocial.requestPermission
to the rescue again! In a method
similar to one used in Chapter 3, Getting Additional MySpace Data, where we requested
permission to fetch photos, we can request permission here to raise an activity:
function raiseActivityCallback(response) {
// Check for an error
if(response.hadError()){
// Was the error a permission issue?
if(response.getErrorCode() ===
opensocial.ResponseItem.Error.UNAUTHORIZED){
// Beg for permission
var reason = "To inform your friends of your upcoming match!";
// Pick which permission
// STICK IT IN AN ARRAY!!
var perm = [MyOpenSpace.Permission.VIEWER_SEND_UPDATES_TO_FRIENDS];
// Pretty please ...
opensocial.requestPermission(perm, reason, actPermCallback);
}
else{
// Some other error
log("Oops, there was an error, try refreshing!");
}
}
}
If there was an error, we first check whether it was a permissions error. If so, we spec-
ify why we want the permission and which permission we want. Again, don’t forget to
stick the
MyOpenSpace.Permission
object into an array or it will be rejected. Once
requestPermission
is closed, it will invoke the specified callback function. Let’s take a
look at it:
function actPermCallback(response){
// Was permission granted?
if(!response.hadError()){
// Yay!
raiseActivity();
}
}
Getting Your App Listed on the Friend Updates
87
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Very simple; if no new permissions were granted, the response has an error. No error
means the permission has been granted, so retry the activity.This is a great way to
ensure that the activity is sent while also providing a nice flow for the user.
Sending Notifications
The fourth and final way to communicate with your users is the app notification.
Notifications are great for turn-based games as they are a quick and easy way to let
players know when it’s their turn in the game.This is exactly how we use them in our
Tic-Tac-Toe app. It’s also highly regarded because it’s the only message type that doesn’t
require the user’s confirmation.
When using notifications, you have to watch that you’re not spamming your
users.You could be shut down, or worse, you’ll annoy your user base and lose
installs. But, if you keep it reasonable, notifications are a great way to increase user
engagement.
When a user gets a notification, he or she gets an indicator on the Home page saying
a new notification has arrived. Clicking on the indicator takes the user to the Mail
Center, where he or she will see the message in the notification folder. Each notification
can have zero to two buttons to allow the user to take some action. In our Tic-Tac-Toe
app, we tell users it’s their turn and provide one button to take them back to the Canvas
page to play the game.
Notifications are a MySpace-specific extension, but they are patterned after
requestCreateActivity
, so the code should be somewhat familiar. Let’s take a look at
what that means:
// Wrap requestCreateNotification
function rsmNotification(recipient, game_id){
// Create the body text
var body = "Hi ${recipient}, it's now your turn";
body += "in <a href='${canvasUrl}'>Tic-Tac-Toe</a>!";
// Create the button that links to the Canvas
var url1 = MyOpenSpace.NotificationButton.UrlTypes.CANVAS;
var params1 = { "game_id" : game_id, "recipient" : recipient };
var text1 = "Take Your Turn!";
var button1 = MyOpenSpace.newNotificationButton(url1, text1, params1);
// Create the button that links to the app's Profile
var url2 = MyOpenSpace.NotificationButton.UrlTypes.APP_PROFILE;
var text2 = "Check out Tic-Tac-Toe";
var button2 = MyOpenSpace.newNotificationButton(url2, text2);
var param = {};
88
Chapter 5 Communication and Viral Features
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
param[MyOpenSpace.Notification.Field.BODY] = body;
param[MyOpenSpace.Notification.Field.BUTTONS] = [button1, button2];
var mediaItemArray = [];
mediaItemArray.push(opensocial.newMediaItem(
"",
MyOpenSpace.MediaItemHelper.PROFILE_PICTURE));
param[MyOpenSpace.Notification.Field.MEDIA_ITEMS] = mediaItemArray;
var notification = MyOpenSpace.newNotification(param);
MyOpenSpace.requestCreateNotification(
recipient,
notification,
rsmNotificationCallback);
}
Notifications use a built-in template, similar to
requestShareApp
. However, only the
variables
${recipient}
and
${canvasUrl}
are available, and you’ll need to use the
activities-style variable format
${variable_name}
, as opposed to the
requestShareApp
style of
[variable_name]
.
The button is defined by a
MyOpenSpace.NotificationButton
object.This object
has three fields:
n
MyOpenSpace.NotificationButton.URL
n
MyOpenSpace.NotificationButton.PARAMS
n
MyOpenSpace.NotificationButton.TEXT
The
URL
can be one of two values:
MyOpenSpace.NotificationButton.
UrlTypes.CANVAS
or
MyOpenSpace.NotificationButton.UrlTypes.
APP_PROFILE
.
You probably won’t want to take your users back to your app Profile, especially con-
sidering that only users who have installed the app receive notifications. Here, we want
to take the user back to the Canvas instead.
The
PARAMS
field allows us to define custom parameters that are sent into the Canvas
page. In our Tic-Tac-Toe app, we append three custom parameters—essentially creating a
tracking parameter.This parameter is used to let us know that a user came to the Canvas
from a notification, what action the user wants to take, and which game the user wants
to play.
Once the button is created, we’re ready to create the
MyOpenSpace.Notification
object itself.We assign the body text first, using
MyOpenSpace.Notification.Field.BODY
,
and then add the button using
MyOpenSpace.Notification.Field.BUTTONS
.The button
has to be placed in an array, so if you have more than one button, you’d add each one to the
array. Omitting the
BUTTONS
parameter or passing in an empty array would just attach no
buttons to the message.
Sending Notifications
89
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
The notification is then sent off using a recipient ID, the notification object, and a
callback.The recipient can be a single ID or an array of IDs, up to a maximum of ten.
The callback behaves exactly like the other callbacks mentioned earlier, so we won’t go
into detail.
A sent notification will appear in the recipient’s Mail Center page; see Figure 5.9 for
exactly how it’ll look.
Tip
Notifications use the permission
MyOpenSpace.Permission.VIEWER_SEND_
NOTIFICATIONS
. You may want to use
opensocial.hasPermission
(followed possibly by
opensocial.requestPermission
) to check that permission before attempting to send
the message. See Chapter 3 to learn how to check and request permissions.
Summary
The primary source of growth for most apps is friend-to-friend advertising. A user
installs the app and then invites a few friends, or a posting appears in the Friend Updates
feed with a link to the app. Either way, the app developer has written various activities,
messages, and invitations as a way of advertising and seeding the application.
It’s important to remember that while these tools must be used, they should never be
abused.An app that’s spammy will quickly annoy users, leaving you with few installs and
a declining user base.
Note
Code listings and/or code examples for this chapter can be found on our Google Code
page under .
90
Chapter 5 Communication and Viral Features
Figure 5.9
The notification in the recipient’s Mail Center page
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
6
Mashups and External Server
Communications
T
he Web is a big place. A very big place.With lots of smart people doing lots of smart
and clever things. Sometimes other people get to use their smart ideas. Sometimes your
needs are so specific that you have to write your own services. Whatever your needs, you
will likely reach a point where the “out-of-the-box” offerings from OpenSocial on
MySpace are just not enough to satisfy your needs.Thankfully, OpenSocial recognizes
these needs and provides you with a mechanism or two for communicating with
external servers.
In this chapter we’ll add two different features to our app that are dependent on
external server communications. Each feature will use a different technique.We will
make use of existing services on the Web to create a “mashup”-style app.
Communication with your own servers, and securing those channels, will be covered
when we discuss other styles of applications.
Communicating with External Servers
What Is an External Server?
An external server is any server whose DNS address does not resolve to the same
top-level domain as the main hosting page. The Web browser imposes multiple security
constraints when dealing with an external server, particularly with regard to cookies and
XMLHttpRequest
(XHR) calls.
In the case of apps, an external server can also be considered any server that is not
under the control of MySpace. The two notions are close enough to be interchangeable
for most discussions in this book.
The main MySpace top-level domain is myspace.com, but all apps are hosted in the
domain msappspace.com, also referred to as a “jail domain” since it restricts apps’
access to the parent page via the same-origin policy regarding source domains.
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
OpenSocial recognizes that it can’t be all things to all people. In fact, it’s designed to be
just some things to all people—namely, an API for exposing social information.To that
end it really is designed for use in external applications and mashups.
There are a multitude of techniques for communicating with external servers. If all
you are doing is referencing static content, there are almost no constraints. If you want to
do something a little more dynamic, like invoke a Web service, things are a little more
complicated.
As we said before, static content on external servers has very little in the way of con-
straints. So long as you use a fully qualified address, the image file will resolve from any
server.This is a common technique for large Web sites.They make use of a content
delivery network, or CDN. A CDN may be simple or complex. A simple CDN just
offloads the bandwidth that would be used to serve static content from the dynamic app
servers, leaving more bandwidth and processing power for handling dynamic requests.
Most browsers also throttle the number of concurrent connections back to a single
domain, so this technique allows the browser to download more files at once; therefore
the page loads faster.
Dynamic content is another story.There are a handful of well-established techniques
for creating dynamic content, some legitimate, some nefarious.We’ll cover the well-
established techniques here and touch on the nefarious ones in Chapter 13,
Performance, Scaling, and Security.
Mashups
92
Chapter 6 Mashups and External Server Communications
Origin of Mashups
A mashup is a Web site or Web application that seamlessly combines content from more
than one source into an integrated experience. The first mashups were simply hackers
reverse-engineering the map APIs from companies like Yahoo! and MapQuest to make
interesting overlays, such as laundromats near you. Over time, the mashup was recog-
nized as not cannibalizing business but being a new business and application model in
the Web 2.0 universe.
While direct information is cloudy, the term
mashup
itself is likely derived from a prac-
tice in music where two different-source music tracks are combined, often through digital
manipulation, to create something entirely new. An example of this would be mixing
Madonna’s “Like a Virgin” vocals over heavy drum and bass instrumentals.
Mashups are a combination of one or more services in a new way to make a new service
or product that is different from the original.
As companies have recognized the value of allowing external parties to use their serv-
ices and infrastructure, the number of open APIs catering to mashup-style applications
has proliferated widely. Several new business models have emerged, allowing larger
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.
ptg
Adding a Feed Reader to Our App
93
providers to leverage their services and infrastructure for new revenue streams by
providing so-called cloud services to third parties.This is in sharp contrast to the
reaction to what we’ll call “proto-mashups” from the early days of the Web. Back then it
was common practice for preportal aggregation sites to either deep-link to buried serv-
ices within another site (for example, linking to buying concert tickets via TicketMaster
from a band review site) or completely hijack a competitor’s content by using framesets
to make their site look like the competitor’s.
Pitfalls of Deep Linking
A number of court cases have resulted in deep linking being declared illegal. The
decisions were largely based on the fact that the deep linker/framer (utilizing site) used
the content for commercial gain without the consent of the content generator (service
site). The practical reasoning is that the utilizing site was using the service site as a
nonconsenting content provider and bypassing the service site’s advertising to show the
utilizing site’s own ads. This was a contentious issue for some time—so contentious, in
fact, that the W3C felt the need to publish a paper arguing that deep linking should be
legal since that is one of the major ways information interacts on the Web. In practice,
deep linking has been difficult to prosecute. A cease-and-desist letter has been the
action of choice for any company attempting to protect its content, and it has usually
been successful.
Almost every major Internet player has some sort of open API to cater to mashup
applications. Content feeds continue to be a major component. As we transition to “Web
2.5/3.0,” consisting of cloud services and user-generated content, a number of new
APIs are also emerging. More obvious and pedestrian applications come in the form of
hosted databases (like Amazon’s SimpleDB service) and various app-hosting services.
Among the newer services are those that help spread the reach of user-generated con-
tent across the Web, like Google’s Blogger Data API, Digg’s user ratings, and MySpace’s
own PostTo endpoints.
Adding a Feed Reader to Our App
We’ll now extend our app by adding a feed reader.This feature allows your users to
never have to leave their game to keep up with the latest happenings on the Web. In the
interest of theatrics, we’ll do this as a contrasting implementation in three parts.We’ll add
a standard set of feeds for the user to select from.Then we will demonstrate three differ-
ent implementations using
makeRequest
:
n
Manual display using the FEED content type
n
Manual display using the DOM content type
n
Raw text response of the feed with TEXT content type
From the Library of Lee Bogdanoff
Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark.