You are here: Docs Technical Documentation Clearspring APIs In-Widget API Share

Share

Sharing Services (beta)

share allows you to post to and retrieve from the same services we use for sharing with our service menu. Useful if you need tighter integration of our sharing services with your application, or the most freedom to customize presentation. Why remake the wheel and worry about integration and uptime when we can handle it all on your behalf? All services are asynchronous, which means you must provide us with a callback so that we can tell you

  • whether the call succeeded
  • what data was returned, if applicable, as a native object. If the call failed, the error code is stored in the object's "error" field.

Contents

API Reference

Name Type Description
share.get method Retrieve data from a sharing service
share.put method Post to a sharing service

share.get

method

Gets data from a sharing service. For example, you'd use this method to retrieve a list of a user's blogs to allow them to select a blog for posting content to.

Parameters
Name Type Required Purpose
service string yes Which service to use. At present, we offer reads from two popular blogging platforms, and an HTML tag generator. Possible values:
  • blogger
  • tag
  • typepad
post data object ex: {username: value, password: value2} no For reading a user's blogs, two key-value pairs are required: username and password. Configuration data may be passed here too, as in share.put.
callback function with signature (status:Number, return:Object) yes The first parameter is 0 iff. the call succeeded; a nonzero value indicates an error. The second parameter contains a native object mapping returned keys to their url-encoded values. In the case of blog retrieval, the pertinent key is targets, a nested object mapping of blog IDs to names. For example, for a user with a single blog you might be returned {targets: {1: 'My First Blog'}}. You must use the returned ID code for calls to share.put(). The tag generation service contains templated HTML under the key tag. In JavaScript, 'callback' must be the function name, as a string.
Return
None
Example Usage

AS2

function callback(status:Number, result:Object)
{
if (status)
{
trace('Houston, we have a problem: ' + result.status);
}
else
{
trace('Got blogs from blogger');
for (var k:String in result)
{
trace(k + '=' + result[k]);
}
}
}
_level0.cs.share.get('blogger',
{username: 'user@example.com', password: '@verys3curep@ssw0rd'},
callback);

AS3

function callback(status:Number, result:Object)
{
if (status)
{
trace('Houston, we have a problem: ' + result.status);
}
else
{
trace('Got blogs from blogger');
for (var k:String in result)
{
trace(k + '=' + result[k]);
}
}
}
_api.share.get('blogger',
{username: 'user@example.com', password: '@verys3curep@ssw0rd'},
callback);

JavaScript

function callback(status, result)
{
if (status)
{
alert('Houston, we have a problem: ' + result.status);
}
else
{
alert('Got blogs from blogger');
for (var k in result)
{
trace(k + '=' + result[k]);
}
}
}
_api.share.get('blogger',
{username: 'user@example.com', password: '@verys3curep@ssw0rd'},
callback);
back to table

share.put

method

Posts data to a sharing service. This is the meat of our viral sharing entree. Posting to MySpace, sending an email, even generating an embed tag (grouped here since it requires storing placement data in our system)--they're all here. Because the services use a variety of input parameters, for ease of reading they're presented separately after the main table.

Also, we group services into two main categories: Get/post and URL exchange. The former are like MySpace--we actually post to a MySpace profile on behalf of the user. If your callback indicates success, the widget actually exists in public. The latter instead work by generating a URL that an end user must click to add your widget to their page. We recommend you play with the services before releasing any applications so you can appreciate their distinctions--every service works differently.

Parameters
Name Type Required Purpose
service string yes Which service to use. Get/post:
  • blackplanet
  • blogger
  • email
  • freewebs
  • friendster
  • hi5
  • multiply
  • myspace_comment - leaves widget in a comment (requires recipient's approval)
  • myspace_profile - posts to myspace profile
  • orkut
  • tag - HTML generation and templating service
  • tagged
  • typepad
  • xanga

URL exchange:
  • eons
  • facebook
  • google
  • live
  • myspace_urlx
  • myyearbook
  • netvibes
  • pageflakes
  • webwag

Bookmarks:
  • aolbookmarks
  • askmystuff
  • backflip
  • blinklist
  • blogmarks
  • browserbookmark
  • digg
  • delicious
  • diigo
  • dropjack
  • faves
  • furl
  • googlebookmarks
  • linkagogo
  • livefavorites
  • netvouz
  • newsvine
  • propeller
  • reddit
  • segnalo
  • simpy
  • spurl
  • stumbleupon
  • technorati
  • twitter
  • yahoobookmark
  • yahoobookmarks
post data object {parameter: value, parameter2: value2...} yes See the following table
callback function with signature (status:Number, dataObject:Object) yes The first parameter is zero iff. the call succeeded; a nonzero status indicates an error. The second parameter contains a native object mapping returned keys to their url-encoded values. In JavaScript, 'callback' must be the function name, as a string. See below for details on the return object format.
Standard Parameters

All of the services can be provided with these optional post data parameters.

Name Type Purpose
config object If you want to override any of your Clearspring-stored configuration parameters for a particular placement, pass them in this config parameter as an object hash mapping keys to values (e.g., {color: "blue", number: 6}). Additionally, new parameters may be added on the fly and templated in.
content HTML If provided, we'll post the contents of this field instead of your widget; useful for dynamic widgets, and for posting alternative content to different sites. Can be templated dynamically.
unique boolean If true, any provided content will be stored in the placement record; this means your actual widget will not be updated. If unique is not specified, then any passesd content will update the master widget record. Due to the power of this parameter, you must additionally pass your Clearspring user ID to provide non-unique content.
userId string See above. Clearspring user ID. Only required for non-unique shares of arbitrary content. N.B.: We strongly discourage passing this parameter in a production widget, as no matter how obfuscated you make it, your widget code can ultimately be compromised once it's in the wild due to the interpreted nature of both Flash and JavaScript.
bug boolean False by default. If set to true, a tracking bug will be included with your post. Only needed if your content doesn't include a kernel of its own.

Service-specific Parameters

Only get/post services require parameters. Any get/post service not listed here has the same standard parameters: username and password are required; comments is optional. Every parameter value must be a string.

Service Additional Parameters
blogger
  • username (required)
  • password (required)
  • target (required) - internal ID code of the blog to post to (not the human-readable name)
  • title (required) - title of the blog post to create
  • comments (optional) - text to include with the widget in the post
email
  • sender (required) - name of the sender (e.g., 'gabi')
  • recipient (required) - email address to send to (e.g., 'ryan@example.com');
  • message (optional) - personal message to include (e.g., 'this widget is teh r0ckz0rz!')
  • widgetHomepage (optional) - link to widget on your site; if omitted, we'll provide a standard clearspring homepage
myspace_profile
  • username (required)
  • password (required)
  • target (required) - one of AboutMe, Books, Heroes, LikeToMeet, Music, Movies, Television
  • comments (optional) - text to include with the widget in the post
myspace_comment
  • username (required)
  • password (required)
  • friendId (required) - friend's profile ID to comment on (found in the profile's URL; e.g., to post to myspace.com/tom, friendId would be set to tom)
typepad
  • username (required)
  • password (required)
  • target (required) - internal ID code of the blog to post to (not the human-readable name)
  • title (required) - title of the blog post to create
  • comments (optional) - text to include with the widget in the post
Return
Nothing.
Callback (status, dataObject)

The status code will be 0 on a successful post; a nonzero integer indicates an error.

The dataObject is particularly significant for URL exchanges. Two keys are returned on success:

  • urlExchange (boolean) - set to true
  • url (string) - the actual URL to open
We return the urlExchange parameter so that you can easily use a single callback to handle both get/post services and URL exchanges.

 

For get/post services, the data object is generally irrelevant; one special case exists, however:

CAPTCHA

If the post fails, it's possible it did so due to a CAPTCHA response required from the user to verify that the third-party service isn't being abused by evil spam robots. If a CAPTCHA is required, the status code will be 2007. The result object will contain all of your original parameters as well as a captcha_url field, containing a string URL to a CAPTCHA image. You must display the image and request that the end user enter the text shown; you must then add this string as the parameter captcha_response to the original result object and resubmit the request. Essentially, you just have to read captcha_url, insert captcha_response, and try again.

At present, only MySpace and Orkut ever require CAPTCHAs.


Example Usage
With CAPTCHA:

AS2

function postToOrkut(fields:Object, captchaText:String)
{
if (captchaText) fields.captcha_response = captchaText;
_level0.cs.share.put('orkut', fields, orkutHandler);
}

function orkutHandler(status:Number, result:Object)
{
if (status)
{
if (result.captcha_url)
{
// Display the captcha image.
// Gather the end user's response and call
// postToOrkut() again with the CAPTCHA text
showCaptchaImage(result.captcha_url);
}
else
{
trace('Error! ' + status);
}
}
else
{
trace('Posted to Orkut');
}
}

function showCaptchaImage(url:String)
{
// ... Left as an exercise for the reader

// Show CAPTCHA, solicit user's input and call postToOrkut() again
// with captchaText set
}

AS3

function postToOrkut(fields:Object, captchaText:String)
{
if (captchaText) fields.captcha_response = captchaText;
_api.share.put('orkut', fields, orkutHandler);
}

function orkutHandler(status:Number, result:Object)
{
if (status)
{
if (result.captcha_url)
{
// Display the captcha image.
// Gather the end user's response and call
// postToOrkut() again with the CAPTCHA text
showCaptchaImage(result.captcha_url);
}
else
{
trace('Error! ' + status);
}
}
else
{
trace('Posted to Orkut');
}
}

function showCaptchaImage(url:String)
{
// ... Left as an exercise for the reader

// Show CAPTCHA, solicit user's input and call postToOrkut() again
// with captchaText set
}

JavaScript

// Note: Not available in JS container

function postToOrkut(fields, captchaText)
{
if (captchaText) fields.captcha_response = captchaText;
_api.share.put('orkut', fields, orkutHandler);
}

function orkutHandler(status, result)
{
if (status)
{
if (result.captcha_url)
{
// Display the captcha image.
// Gather the end user's response and call
// postToOrkut() again with the CAPTCHA text
showCaptchaImage(result.captcha_url);
}
else
{
trace('Error! ' + status);
}
}
else
{
trace('Posted to Orkut');
}
}

function showCaptchaImage(url)
{
// ... Left as an exercise for the reader

// Show CAPTCHA, solicit user's input and call postToOrkut() again
// with captchaText set
}

 

Tag generation:

AS2

function tagHandler(status:Number, result:Object)
{
if (status)
{
trace('Error: ' + status);
}
else
{
trace('Got a tag');
trace(result.tag); // note that tag is returned in result.tag
}
}
_level0.cs.share.put('tag', {}, tagHandler);

AS3

function tagHandler(status:Number, result:Object)
{
if (status)
{
trace('Error: ' + status);
}
else
{
trace('Got a tag');
trace(result.tag); // note that tag is returned in result.tag
}
}
_api.share.put('tag', {}, tagHandler);

JavaScript

// Note: Not available in JS container

function tagHandler(status, result)
{
if (status)
{
trace('Error: ' + status);
}
else
{
trace('Got a tag');
trace(result.tag); // note that tag is returned in result.tag
}
}
_api.share.put('tag', {}, tagHandler);
back to table


Error Codes

Code Description
2000 Catastrophic failure
2001 Invalid destination
2002 Placement creation failed
2005 Unable to contact destination
2007 CAPTCHA required
2008 Get/Post login failed
2009 Get/Post HTTP error
2011 Posting to service failed
2012 Invalid targets list
2013 No content provided
2015 Invalid username
2016 Invalid password
2017 Content size limit exceeded
2018 Content not provided or found



Templatable Content

When using dynamic content sharing, we will replace a few key text strings in all share services.

Name Purpose
{{_CS_WID}} Replaced with Clearspring widget ID. Useful if you're using one basic code base with a few different kernels to partition your analytics.
{{_CS_PID}} Replaced with Clearspring placement ID. Arguably the most important templated field. This allows you to use our share services without our container and still get a meaningful Viral Hubs report. You just pass us back the PID we generate at share time, and we're able to distinguish between kernel placements.
{{flv_*}} Any configuration parameter can be replaced this way; e.g., the parameter color could be templated by inserting {{flv_color}} into your content. Then all placements will reflect the set color. This means you can use our regular configuration management system with arbitrary content, allowing you to maintain a master content template and just store configuration data at the placement level.

Example Templates

This content template would allow the user to specify their own configuration parameter 'videoId' with each share. The main template would only have to be set up once, making specific share calls simple (e.g., share.put(destination, {config: {videoId: 198371}}, callback)).

Flash

<object type="application/x-shockwave-flash" data="http://widgets.example.com/main.swf" 
id="w{{_CS_WID}}{{_CS_PID}}" height="200" width="200">
<param value="http://widgets.example.com/main.swf" name="movie"/>
<param value="transparent" name="wmode">
<param value="videoId={{flv_videoId}}" name="flashvars">
<param value="all" name="allowNetworking">
<param value="always" name="allowScriptAccess">
</object>

JavaScript

<script type="text/javascript" 
src="http://widgets.example.com/video.js?pid={{_CS_PID}}&videoId={{flv_videoId}}">
</script>

Tutorial

This tutorial will cover a realistic use case for using the kernel in a Flash (AS2) video player. It assumes a basic knowledge of Flash and our web console.

Step 1. Obtain a new kernel code snippet from the console.

Let's say this was our sample code:

System.security.allowDomain("bin.clearspring.com");
System.security.allowDomain("widgets.clearspring.com");

var kernelUrl:String = "http://widgets.clearspring.com" +
"/o/47c5ce8a742be614/47c5ce8a742be614/-/-TRK/1/lib.as2.swf?onLoad=onLibLoad";
var kernel:MovieClip;

function onLibLoad(k:MovieClip)
{
kernel = k;
// Send a custom event
kernel.track.event('Kernel loaded');
trace('You have viewed this widget ' +
kernel.context.user.WIDGET_VIEWS + ' times');
}

var kernelContainer:MovieClip = _root.createEmptyMovieClip("clearspring",
_root.getNextHighestDepth());
var mcl:MovieClipLoader = new MovieClipLoader();
mcl.loadClip(kernelUrl, kernelContainer);

 

Step 2. Insert the sample code into the widget. We can put this right on the main timeline if we're using the IDE; if we're using MTASC or another third-party compilation tool, we'd wrap it in its own class. That exercise is left for the reader.

All the tracking and so forth begins from the moment kernel loads, so we'll insert this as close to the start of our widget's life as possible.

Step 3. Register the content that we want to share. This is the hardest part. We have APIs for doing so, but because they require you to provide your Clearspring user ID, you won't want to actually release an application using them in the wild. Noting that, we just have to modify post-kernel-load initialization method. (New code in blue, deleted code in red.)

function onLibLoad(k:MovieClip)
{
kernel = k;

// We can delete this because it's just for demonstration purposes:

// Send a custom event
kernel.track.event('Kernel loaded');
trace('You have viewed this widget ' +
kernel.context.user.WIDGET_VIEWS + ' times');


// We add this to update our content (blank by default):

var myContent:String = "Some content"; // just a placeholder for now
kernel.widget.update('CLEARSPRING-USER-ID', // available in console under Settings
'47c5ce8a742be614', // widget ID from sample code
{content: myContent,
width: 425, height: 355, // dimensions of your widget
config: {videoId: ''}}, // we'll use the configuration later
onUpdate);

}
// We add this so we're notified when the call goes through

function onUpdate(status:Number, result:Object)
{
if (status) {
trace('An error occurred: ' + status);
} else {
trace('Widget successfully updated!');
}
}

 

Now we run our widget, and if all goes well you should see 'Widget successfully updated!' traced out. Note that you must

  • insert your own user ID
  • insert your own widget ID
  • insert your own widget dimensions
  • insert your own widget parameters
to use this example with your own code.

 

Step 4. Define meaningful content. So we're interfaced with the widget.update call, but now we need to actually register real content and not just the simple placeholder "Some content". For this example, we'll use a YouTube video. You should use an object tag referring to your actual Flash movie.

The tag:

<object width="425" height="355"><param name="movie" 
value="http://www.youtube.com/v/IcgfdtkcIW0&rel=1"></param>
<param name="wmode" value="transparent"></param>
<embed src="http://www.youtube.com/v/IcgfdtkcIW0&rel=1"
type="application/x-shockwave-flash" wmode="transparent" width="425"
height="355"></embed>
</object>
So we just update myContent to be this string:
var myContent:String = '<object width="425" height="355"><param name="movie" 
value="http://www.youtube.com/v/IcgfdtkcIW0&rel=1"></param>
<param name="wmode" value="transparent"></param>
<embed src="http://www.youtube.com/v/IcgfdtkcIW0&rel=1"
type="application/x-shockwave-flash" wmode="transparent" width="425"
height="355"></embed></object>';
and re-run the widget to update the content stored in our database. Calling share.put now would push this particular YouTube video anywhere. Try it out!
	// ... in onLibLoad
kernel.share.put("google", {}, onUrlExchange);
// ...
// ...
function onUrlExchange(status:Number, result:Object):Void
{
if (status) {
trace('Error: ' + status);
} else {
// Open iGoogle in a new window
getURL(result.url, "_blank");
}
}

 

Step 5. Template our content. We want to have unique placement IDs for every instance of our widget, so that we can get the best possible reporting. (By default, since the kernel only is referenced by a single ID, we can't tell different placements apart.) Moreover, we want to be able to push different YouTube videos using the same widget. So we add two templatable variables to our template: {{_CS_PID}}, which gives us a unique placement ID, and {{flv_videoId}}, which lets us easily configure different placements to show different videos.

var myContent:String = 	'<object width="425" height="355"><param name="movie" ' +
'value="http://www.youtube.com/v/' +
'{{flv_videoId}}&pid={{_CS_PID}}&rel=1">' +
'</param>' +
'<param name="wmode" value="transparent"></param>'+
'<embed ' +
'src="http://www.youtube.com/v/' +
'{{flv_videoId}}&pid={{_CS_PID}}&rel=1"' +
'type="application/x-shockwave-flash" wmode="transparent"' +
'width="425" height="355"></embed></object>';
Obviously, the YouTube player doesn't actually have our kernel in it. But pretending your project is the video player, you'd pass the pid parameter to us by modifying kernelUrl:
 
var kernelUrl:String = "http://widgets.clearspring.com/o/47c5ce8a742be614/" +
pid + "
/-/-TRK/1/lib.as2.swf?onLoad=onLibLoad";

 

(For you non-Flash developers: query-string parameters like pid are automatically inserted as global variables into simple ActionScript 2 projects. Your mileage may vary.)

Step 6. Pass configuration to share calls. The only piece left is to call share.put with different configurations. Choose your favorite videos! Or reference your own content.

For example, these two calls should open two new windows, each trying to place a different video on your iGoogle page.

	kernel.share.put("google", {config: {videoId: 'G6CE5mYuMbI'}}, onUrlExchange);
kernel.share.put("google", {config: {videoId: 'tmJ_a5GBVl4'}}, onUrlExchange);