Use Macromedia Flash Local Shared Objects Instead of Cookies





Use Macromedia Flash Local Shared Objects Instead of Cookies

Leverage the ubiquity of Macromedia's Flash and Local Shared Objects instead of cookies.

Recent data presented by JupiterResearch suggests that the availability of cookies for use in measurement applications is at greater risk than many previously believed. One response to the "decline of cookies" is to look for other systems for tracking new and returning visitors. This hack describes a workaround based on Macromedia Flash's Local Shared Object. According to the fine folks at Macromedia:

Shared Objects are used to store data on the client machine in much the same way that data is stored in a cookie created through a web browser. The data can only be read by movies originating from the same domain that created the Shared Object. This is the only way Macromedia Flash Player can write data to a user's machine. Shared Objects can not remember a user's e-mail address or other personal information unless they willingly provide such information.

The important pieces of this definition are "much in the same way that data is stored in a cookie, " "can only be read by movies originating from the same domain that created the Shared Object, " and "Shared Objects can not remember a user's e-mail address or other personal information unless they willingly provide such information." Put another way, Local Shared Objects are a perfect replacement for cookies because they're just as secure and just as harmless.

The JavaScript Code

The following script tests for when the Flash movie should be embedded in the page and provides a function for setting the secondary cookie. There are three main configuration parameters:

  • myUIDCookie is the name of the unique ID cookie employed on your site. The default for Apache's mod_usertrack module is "Apache."

  • myUIDFlashCookie is the name you wish to be used for the secondary cookie created by this system.

  • mytrackingURL is the URL on your tracking server where the set and recover events are to be recorded.

Additionally, you will need to specify the location of Flash in the object and embed tags written into the page by the script. Be sure to change the URL in both locations.

	// A simple system for testing the ability to recover
	// from deleted user cookie using Flash's local
	// shared objects.

	// Configure Cookies to use. The first is the normal
	// user cookie name employed on the site. The second
	// is an additional cookie to be used for identification
	// of cookie removal and cross deletion tracking.

	var myUIDCookie = "Apache";
	var myUIDFlashCookie = "FlashID";

	// Configure a trackable image request that can be 
	// used to count the resets. The URL must end with 
	// a ? or an & as the flash will be appending a few 
	// name value pairs. 
	// Modify the URL with the tracking server
	var myTrackingURL = escape('http://www.yoursite.com/some/tracking/call?');
	// Test if the Cookie set by the flash movie exists and
	// if it doesn't embed it while passing it TrackingURL and
	// the value of the myUIDCookie cookie.

	var Cookies = document.cookie;
	if (Cookies.indexOf(myUIDCookie + "=") != -1) { 
	 // myUIDCookie does exist - system re	quires it even if it is a new one 
	 var CookieStart = Cookies.indexOf(myUIDCookie + "=") + myUIDCookie.length + 1; 
	 var CookieEnd = Cookies.indexOf(";", CookieStart); 
	 if (CookieEnd == -1) CookieEnd = Cookies.length; 
	 var myUIDCookieValue = Cookies.substring(CookieStart, CookieEnd);

	 //write value of user id cookie 
	 document.write('<p><font color="red">Your Unique ID Cookie is '
		 + myUIDCookieValue + '</font></p>');

if (Cookies.indexOf(myUIDFlashCookie + "=") == -1) {
	  // myUIDFlashCookie doesn't exist embed the flash
	  document.write('<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-
     444553540000" codebase="http://fpdownload.macromedia.com/pub/ 
		 shockwave/cabs/flash/swflash.cab#version=6, 0, 0, 0" width="1" 
		 height="1" id="flashtrack" align="middle">');
	  document.write('<param name="allowScriptAccess" value="sameDomain" />'); 
	  document.write('<param name="movie" value="/scripts/flashtrack 
	   flashtrack.
  swf?UIDCookieValue='+myUIDCookieValue+'&TrackingURL='+myTrackingURL+'" />');
	  document.write('<param name="loop" value="false" />'); 
	  document.write('<param name="menu" value="false" />'); 
	  document.write('<param name="quality" value="best" />'); 
	  document.write('<param name="scale" value="noscale" />'); 
	  document.write('<param name="wmode" value="transparent" />'); 
	  document.write('<param name="bgcolor" value="#ffffff" />'); 
	  document.write('<embed src="/scripts/flashtrack/flashtrack.
  swf?UIDCookieValue='+myUIDCookieValue+'&TrackingURL='+myTrackingURL+'" 
   loop="false" menu="false" quality="best" scale="noscale" wmode= 
	 "transparent" bgcolor="#ffffff" width="1" height="1" name="flashtrack"
  align="middle" allowScriptAccess="sameDomain" type= 
   "application/x-shockwave-flash" pluginspage="http://www.macromedia.com/ 
   go/getflashplayer" />');
	  document.write('</object>');
	 } else {
	  // Code may be placed here to do something with the value of
	  // the flash set cookie when it already exists.

	  //write value of the Flash Cookie
	  var FCookieStart = Cookies.indexOf(myUIDFlashCookie + "=") +

  myUIDFlashCookie.length + 1; 
	  var FCookieEnd = Cookies.indexOf(";", FCookieStart); 
	  if (FCookieEnd == -1) FCookieEnd = Cookies.length; 
	  var myUIDFCookieValue = Cookies.substring(FCookieStart, FCookieEnd); 
	  document.write('<p><font color="blue">Your Flash UID Cookie was already
	   set to ' + myUIDFCookieValue + '<br>so the flash was not loaded 
		 and no tracking call made.</font></p>'); 
   } 
  }
  // A special function is called by the flash to set 
  // the cookie that returns the user id stored 
  function setFlashCookie(value) {
   var expiration = new Date();
	 expiration.setTime(expiration.getTime() + (365*86400000));
	 document.cookie = myUIDFlashCookie + "=" + value + "; expires=" +
    expiration.toGMTString() + ";path=/;";

   //write value of cookie being set
	 document.write('<p><font color="blue">Your Flash track UID Cookie has been
 set to ' + value + '</font></p>'); 
 }

Remember, for this code to function properly, you need to change both references to /scripts/flashtrack/flashtrack.swf to the actual location of the flashtrack.swf file presented in the next section. You must also modify the reference to http://www.yoursite.com/some/tracking/call? to a URL on your tracking server where the set and recover events are to be recorded.

The Flash ActionScript Code

The next step is to create a Flash movie (.swf) to store and read from the local object. First, create a blank Flash document and set the stage size to one by one pixel. Create a movie file called flashtrack.swf that contains nothing more than a single blank key frame and the following ActionScript:

	stop();

	// create the local Shared Object to store the uid
	myLocalSO = sharedobject.getLocal("flashtrack" );

	// initialize the time variables that will be used
	myDate = new Date();
	myTime = myDate.getTime();

	// test that the required TrackingURL UIDCookieValue parameters were passed 
    and aren't null 
  if ((UIDCookieValue != null) &&(FlashCookieName != null) &&
	  (TrackingURL != null)) { 
	  // test if the local shared object exists and create the appended 
		// tracking url with a name value at the end to illustrate it is being 
		// recovered. 
		if (myLocalSO.data.uid != null) {
	    myTrackingURL =
	unescape(TrackingURL)+"&uidvalue="+UIDCookieValue+"&flashvalue= 
    "+myLocalSO.d	ata.uid+"&origination="+myLocalSO.data.origination+"&action= 
    recover";
    }
		// else set local shared object data if it didn't exist and then the
		// appended tracking url with a name value at the end to illustrate
		// it is being set for the first time.
		else {

		  myLocalSO.data.uid = UIDCookieValue;
			myLocalSO.data.origination = myTime;
			myTrackingURL =

  unescape(TrackingURL)+"&uidvalue="+UIDCookieValue+"&flashvalue=
   "+myLocalSO.data.uid+"&origination="+myLocalSO.data.origination+"&action=set"; 
    } 
	  // define and call the special javascript function that sets the cookie 
	  myCookieURL = "javascript:setFlashCookie('"+myLocalSO.data.uid+"')"; 
	  getURL(myCookieURL); 
	  // use loadMovie to call the tracking url from the server to log the event 
	  loadMovie(myTrackingURL, _root);
  }

Running the Hack

Assuming you've set everything up properly, your should see results that look like the following:

	Your Unique ID Cookie is 204.210.27.229.6793111293290684 
	Your Flash track UID Cookie has been set to 204.210.27.229.29421110768119167 
	it was originally stored on Wed, 16 Mar 2005 15:14:56 UTC

If the two cookie values are the same, it means you currently have the same UID cookie used when the Flash Local Shared Object was stored. Clear your cookies and hard reload the page to see how they will differ.

You can see an example of this script in action by visiting www.visioactive.com/scripts/flashtrack/

A Note About Whether This Is a Good Idea

While we have clearly shown that using Flash's Local Shared Objects is possible as a replacement for cookies, what we have not demonstrated is whether this strategy is actually a good idea. Because concerns among Internet users regarding security and privacy of data persist and may in fact be getting worse rather than better, there is a substantial debate over whether using Flash as a replacement for cookies does more harm than good.

One side argues that any available technology can and should be used to improve the quality of information available to marketers and technologists, working under the assumption that you cannot improve on what you do not truly know. The other side argues that nobody has the right to spy on an anonymous web visitor's activities, and that the contents of this hack do nothing more than enable spying.

While you're free to judge and decide for yourself, consider this: if Flash begins to be used widely for this purpose and the privacy advocates complain loudly enough, Macromedia might be forced to remove the functionality from their application, returning everyone to square one.

You have the information you need. Make your own decision, but choose wisely.

Ian Houston and Eric T. Peterson


     Python   SQL   Java   php   Perl 
     game development   web development   internet   *nix   graphics   hardware 
     telecommunications   C++ 
     Flash   Active Directory   Windows