CARVIEW |
Software
Documentation
Personalization API Developer Guide
The Personalization API introduced in 5.5 contains a ranking engine to help you sort items that users can click. For example, a gadget that displays items from an RSS feed can use the ranking engine to sort feed items.
Contents
Overview
You can use the ranking engine any time your gadget displays an ordered list of items. Just provide an array of rankable items or content items to the ranking engine, and the engine will return a sorted array of those items.
The ranking engine uses attributes such as clicks and the amount of time spent viewing items to determine how to sort the items. For example, if the user clicks every item except one, then by default that unclicked item will be the first item.
You can change how the ranking engine sorts items. For example, you can specify that a particular item should always be first or last. You can also group related items by specifying a data source for each group. Finally, you can not only set the values of attributes (such as clicks), but also specify how the ranking engine uses those attributes to sort items.
API support for ranking is provided by
google.pers.ranking
and
RankableItem
.
Sample Code
Here's how you typically use the ranking API.
- Register to use the API by putting a
<personalizationAPI>
element in your gadget'sgadget.gmanifest
file. For example:<gadget minimumGoogleDesktopVersion="..."> <about> <--! ... usual items such as name, description, and id go here ... --> <personalizationAPI /> </about> </gadget>
- Create a profile
for your gadget. You'll use this profile to identify your gadget whenever
you call the ranking API. Here's an example of creating the profile:
var profile = google.pers.ranking.createProfile("MyGadget");
- Unless you're
ranking the items in a content
area, create a
RankableItem
object for each item you want to be sorted.Note: Skip this step if you use a content area. This method is automatically called whenever the user adds a content item.
For each rankable item, you need to specify an item identifier, a data-source identifier, and the profile. The item identifier can be anything that your gadget uses to identify the item; it might be a string or an array index. The data-source identifier is an application-specific number that you can use to group items. If you don't group items, just use the same data-source identifier for each item. Here's an example of creating
RankableItem
objects for items:var imageArray = new Array(); //one image per item var rankArray = new Array(); //one RankableItem per item ... //Just after an array of clickable items is created: for (var i = 0; i < numItems; i++) { var rankItem = google.pers.ranking.createRankableItem(); rankItem.identifier = i; //set item ID rankItem.updateRankingProfile(1, profile); //set data-source ID & profile rankArray.push(rankItem); //add the rankable item to an array }
- Unless you're
ranking the items in a content area, call an item's
incrementClicksAndUpdateClickedTime()
method whenever the user clicks the item.Note: Skip this step if you use a content area. This method is automatically called whenever the user clicks a content item or its details view's title.
Usually, the value you specify to this method should be 1, but you can use a higher number to indicate that a click was more important. For example, you might use the value 2 for a double-click, or 5 for a click that was somehow as important as 5 ordinary clicks. Here's an example of calling
incrementClicksAndUpdateClickedTime
from anonclick
handler://rankIndex is the index of the selected item rankArray[rankIndex].incrementClicksAndUpdateClickedTime(1);
- Whenever you want to sort items — such as after a click or data refresh —
call the
rankAllItems()
orrankItemsForDataSource()
method. If you need to convert the return value to a JavaScript array, usetoArray()
.//Typical code for a gadget that displays an array of items var selectedItemID = rankArray[rankIndex].identifier; rankArray = google.pers.ranking.rankAllItems( profile, rankArray, rankArray.length).toArray(); //Keep the same selected item as before for (var i = 0; i < rankArray.length; i++) { if (rankArray[i].identifier == selectedItemID) { rankIndex = i; break; } }
For a content area, your code should look like this:
//Code for a content area var itemsToRank = contentArea.contentItems; var rankedItems = google.pers.ranking.rankAllItems( profile, itemsToRank, itemsToRank.toArray().length); contentArea.contentItems = rankedItems;
Attributes that Affect Ranking
The ranking engine sorts items using the attributes shown in the following table. If your gadget has items from multiple data sources — from multiple RSS feeds, for example — then the data source can also affect the item order, as described in the following table.
Attribute Name | Description | Default Effect on Item Score | Default Effect on Other Items |
---|---|---|---|
"NumberOfClicks" | Number of times the item has been clicked.
Automatically set for content areas. To set for non-content areas, use incrementClicksAndUpdateClickedTime() ,
as shown in Sample Code.
|
More clicks = lower item score | More clicks = higher scores for other items from the same data source |
"LastClickedTime" | How much time has passed since the item was clicked.
Automatically set for content areas. To set for non-content areas, use incrementClicksAndUpdateClickedTime() ,
as shown in Sample Code.
|
More time = higher item score | More time = lower scores for other items from the same data source |
"ItemTime" | When the item was published (in an RSS feed).
Ignored unless you set the attribute value. |
More recent = higher item score | none |
"ItemOpenDuration" | The length of time the item's details were viewed.
Automatically set for content areas; ignored for non-content areas unless you set it. To set this attribute value, use the updateItemOpenDuration()
method.
|
More time = lower item score | More time = higher scores for other items from the same data source |
In general, the higher an item's score is, the more prominent the item should be in your gadget's GUI. You don't directly use item scores. Instead, your gadget requests the ranking API to return an ordered array of items, where the first item in the array (index 0) has the highest score. For example, if the user clicks every item except one, then by default that unclicked item will be the first item in the returned array, and your gadget should display it in the most prominent position.
Changing How Items Are Ranked
Although you can't directly change an item's score, you can affect how items are ranked. You can use these techniques:
- Specifying an item's location (always at the top or bottom)
- Changing the value of an item's attribute
- Changing an attribute's weight (raising or lowering its importance)
- Changing an attribute's algorithm (affecting how its score is calculated)
Specifying an item's location
To specify that an item should always be at the top or bottom of the
ranked list of items,
use the
rankType
property
of RankableItem
.
topItem.rankType = contentRankingFlag.AlwaysTop; //put this item at the top botItem.rankType = contentRankingFlag.AlwaysBottom; //put this item at the bottom
Changing the value of an item's attribute
In general, you should use an attribute-specific method
to set the value of an item's attribute.
For example, use
updateItemOpenDuration()
to update the value of
"ItemOpenDuration", and use
incrementClicksAndUpdateClickedTime()
to update the value of
"NumberOfClicks" and "LastClickedTime".
To reset all attribute values in an item, use
resetStatistics()
.
To set the "ItemTime" attribute
or make any other attribute of an item have a specific value,
you need to use the
updateAttributeValue()
method.
The following code shows how to set the "ItemTime" attribute value
for an item.
//Parse the data to get date and time for an item.
...
//Create a Date and set the value of the ItemTime attribute.
var date = new Date(year, month, day, hours, minutes, seconds, ms);
item.updateAttributeValue("ItemTime", date.getTime()/1000);
All attributes have integer values; time-based values are in seconds. The "ItemTime" attribute supports two kinds of date formats:
- UTC date as an integer:
the number of seconds since 1/1/1970 UTC.
Use the code
date.getTime()/1000
to convert a JavaScriptDate
object to this format. - UTC date in VT_DATE format,
as returned by JScript
Date
objects (see thegetVarDate()
method) and by some COM and ActiveX objects.
Changing an attribute's weight
Use modifyAttributeWeight() to increase or decrease the importance of a particular attribute. By default, all attributes start with the same weight (1.0), which makes them equally important. To ignore an element, set its weight to 0.0.
Here's an example of changing the weight of two items, making one more important and the other irrelevant.
//Make item time more important than attributes that have a weight of 1.0. google.pers.ranking.modifyAttributeWeight("ItemTime", 2.0); //Ignore the number of clicks. google.pers.ranking.modifyAttributeWeight("NumberOfClicks", 0.0);
Changing an attribute's algorithm
Use
modifyAttributeAlgorithm()
to specify which algorithm to use
for calculating the score of a particular attribute.
You specify the algorithm using a combination of flags defined by
contentRankingAlgorithm
.
The algorithm has two parts:
- Proportionality — DirectlyProportional or InverselyProportional
- A directly proportional algorithm increases the score as the attribute value increases. An inversely proportional algorithm reduces the score as the attribute value increases.
- Steepness — LeastSteep or MostSteep
-
If you graph the attribute value on the x-axis
and the score on the y-axis,
the curve is flatter for
LeastSteep
than it is forMostSteep
. In other words, "most steep" means that the score increases or decreases more as the attribute value increases. Because a click is usually much more significant than one second of time, by default "NumberOfClicks" usesMostSteep
and time-based attributes useLeastSteep
.
The following table shows the default algorithm used by each attribute.
Attribute Name | Default Algorithm |
---|---|
"NumberOfClicks" | InverselyProportional, MostSteep |
"LastClickedTime" | custom |
"ItemTime" | InverselyProportional, LeastSteep |
"ItemOpenDuration" | InverselyProportional, LeastSteep |
Note: Don't set the algorithm for "LastClickedTime". It always uses a custom algorithm.
The following code
changes the algorithm for the "NumberOfClicks" attribute.
The default algorithm for "NumberOfClicks"
(InverselyProportional
and
MostSteep
)
decreases the score significantly each time the item has been clicked.
If you want the score to increase instead,
you must change InverselyProportional
to DirectlyProportional
.
google.pers.ranking.modifyAttributeAlgorithm(
"NumberOfClicks",
contentRankingAlgorithm.DirectlyProportional | contentRankingAlgorithm.MostSteep);