Hack 18. 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:
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. 2.6.1. The JavaScript CodeThe 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:
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 class codebase="http://fpdownload.macromedia.com/pub/ shockwave/cabs/flash/swflash.cab#version=6, 0, 0, 0" width="1" height="1" 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="/books/4/263/1/html/2//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. 2.6.2. The Flash ActionScript CodeThe 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); } 2.6.3. Running the HackAssuming 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/ 2.6.4. A Note About Whether This Is a Good IdeaWhile 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 |