Navigation |
>> Home |
Enforcing Banners
Written by: Christoph Wille Many users surfing the Net use so called banner blockers (ad blockers), which block advertising banners - a well known tool in this category is the WebWasher. However, there are many Web sites on the Internet financing their contents by means of banner advertising on their pages. For these Web sites, such tools as the WebWasher truly are "Killer Apps" as they effectively filter out their source of revenue. As a colleague of mine uses WebWasher, I sat down with him to discuss the technical possibilites for outwitting WebWasher as a Web site operator:
The last item sounds almost naive, but after some thoughts this was the approach we liked best. The Basic IdeaThe idea behind this is amazingly simple: every modern browser supports CSS and DIV tags. Using CSS, DIV tags can be rendered invisible - it is thus a nearly obvious idea to hide the page content inside an invisible DIV tag until the banners were loaded. In case the banner does not arrive, the DIV tag won't be set to visible - tough luck for the advertisement shy. The toggling from invisible to visible is done using an event on the banner ad image tag. This means that JavaScript must be enabled - this way, we also automatically have a browser test included. In the file bannerpage.htm I have implemented a simple page using this idea: <html> <head> <title>Bannerpage</title> </head> <body> <div id="pleaseWait"> Please wait while the page is being loaded. Should you experience problems, <a href="">please klick here</a>. </div> <div id="mainDiv" STYLE="display:None;"> <p>This content is only displayed after the banner has loaded - together with the Banner.</p> <img src="http://ads.softartisans.com/servead.asp?s=11&b=1" onload="yesImage()"> </div> <SCRIPT LANGUAGE=JavaScript> <!-- function yesImage() { document.all.pleaseWait.style.display = "none"; document.all.mainDiv.style.display = ""; } //--> </SCRIPT> </body> </html> There are two DIV tags - pleaseWait containing the message that the page is being loaded and mainDiv which is hidden and encloses the content of the page which is to be protected. The onload event with the function yesImage is hooked to the image tag - when the event triggers, the image is done loading and the visibility of the two DIV tags is swapped. With this, our content is efficiently protected - should the image be 'killed' by a banner blocker, the event is never triggered. As CSS is automatically executed, the user also will not have a chance to render the content visible (unless he saves the file to disk and modifies the HTML). The idea behind the "please wait" message containing the link is to let the customer who does not get to see the content due to blocking go to a page where he will find a courteous explanation of why he did not get to see anything. On sites with only a few banner ads (such as AspHeute) most visitors will probably not be upset. Implementation in ASPThe HTML page presented has certain disadvantages - the DIV tags have fixed names and would thus be prone to be easily deleted automatically. Therefore we will somewhat 'take this into consideration' in our implementation in ASP - and extend this protection toward the variable and function names in JavaScript as well. I implemented the desired functionality in bannerfunctions.asp which can be included into any file to be protected. The IncludeAn important prerequisite for us is that the names of the DIV tags are not to be set as givens. This suggests that we might adapt the functions of the German-only article Generierung eines sicheren Passworts somewhat: <script language="vbscript" runat="server"> Function GenerateRandom(ByVal Laenge) Dim intI, strRandom strRandom = "" For intI = 1 to Laenge strRandom = strRandom & GenerateCharacter() Next GenerateRandom = strRandom End Function Function GenerateCharacter() Dim intRnd, strRnd Randomize Do intRnd = Int(Rnd * 60) If intRnd >=52 Then strRnd = CStr(intRnd - 51) ElseIf intRnd >= 26 Then strRnd = Chr(Asc("A") + intRnd - 26) Else strRnd = Chr(Asc("a") + intRnd) End If Loop Until (strRnd <> "0" And strRnd <> "l" _ And strRnd <> "I") GenerateCharacter = strRnd End Function </script> By calling the function GenerateRandom we obtain a random string of characters we can use as names for DIV tags, variables and functions as well. GenerateRandom first shows up in the functions ShowWaitMessage and PreCreateSections. <% Dim m_nSections, m_arrSections(), m_strFunctionName, m_nNumberOfImages Dim m_strWaitSection m_nSections = -1 m_nNumberOfImages = 0 Function ShowWaitMessage() Dim strMessage m_strWaitSection = "div" & GenerateRandom(12) strMessage = "<div id=""" & m_strWaitSection & """>" & vbCrlf strMessage = strMessage & Please wait while the page is being loaded. " strMessage = strMessage & "Should you experience problems, " & _ "<a href=""xplain.htm"">please klick here</a>." strMessage = strMessage & vbCrlf & "</div>" & vbCrlf ShowWaitMessage = strMessage End Function Sub PreCreateSections(ByVal nSections) Dim i m_nSections = nSections ReDim m_arrSections(nSections) For i = 0 To (nSections-1) m_arrSections(i) = "div" & GenerateRandom(10) Next m_strFunctionName = "set" & GenerateRandom(15) End Sub In ShowWaitMessage, GenerateRandom is used to generate the name of the DIV tags surrounding the 'please wait' message. The PreCreateSections function serves a very special purpose - after calling it, all the DIV tag sections to be hidden are known by name and can have the corresponding JavaScript rendered using GetDisplayFunction in arbitrary locations (for this however, GetImageFunction would have to be adapted). Function BeginSection(ByVal nSection) If (nSection < 0 Or nSection > m_nSections) Then Response.Write "ERROR: BeginSection - section requested does not exist: " & nSection Response.End End If BeginSection = vbCrlf & "<div id=""" & m_arrSections(nSection-1) & _ """ STYLE=""display:None;"">" & vbCrlf End Function Function EndSection() EndSection = vbCrlf & "</div>" & vbCrlf End Function Function GetImageFunction() GetImageFunction = " onload=""" & m_strFunctionName & "()"" " m_nNumberOfImages = m_nNumberOfImages + 1 End Function Function GetDisplayFunction() Dim strScript, strVariable, i strVariable = "var" & GenerateRandom(10) strScript = "<SCRIP" & "T LANGUAGE=JavaScript>" & vbCrlf strScript = strScript & "<!--" & vbCrlf strScript = strScript & "var " & strVariable & "=" & m_nNumberOfImages & ";" & vbCrlf strScript = strScript & "function " & m_strFunctionName & "() {" & vbCrlf strScript = strScript & strVariable & "--;" & vbCrlf strScript = strScript & "if (0 == " & strVariable & ") {" & vbCrlf strScript = strScript & "document.all." & m_strWaitSection & _ ".style.display = ""none"";" & vbCrlf For i = 0 To (m_nSections-1) strScript = strScript & "document.all." & m_arrSections(i) & _ ".style.display = """";" & vbCrlf Next strScript = strScript & "}" & vbCrlf & "}" & vbCrlf & "//-->" & vbCrlf & _ "</SCR" & "IPT>" & vbCrlf GetDisplayFunction = strScript End Function %> The function BeginSection marks the beginning of a content section, while EndSection marks its end. Why hide several content sections at all? Well, we won't want to make it too easy for blockers to strip out our code, won't we? The GetImageFunction call is important, as it must be called for each image tag to be protected (example will follow immediately). This way the script knows how the JavaScript function in GetDisplayFunction is to be adapted. A Banner-Enforcing PageEnough of preparatory work - now what does the code look like that we have to insert into a page that is to be protected? An example is bannerpage.asp: <% Option Explicit %> <html> <head> <title>Bannerpage</title> </head> <body> <!--#include file="bannerfunctions.asp"--> <%=ShowWaitMessage()%> <%PreCreateSections(2)%> <%=BeginSection(1)%> <p>This content is only diplayed after the Banner has loaded - together with the Banner.</p> <img src="http://ads.softartisans.com/servead.asp?s=11&b=1" <%=GetImageFunction()%>> <%=EndSection()%> <%=BeginSection(2)%> <p>Further text, merely intended to be a demo.</p> <%=EndSection()%> <%=GetDisplayFunction%> </body> </html> First ShowWaitMessage is called, then PreCreateSections creates the sections (in this case, two). Now we can protect the content using BeginSection and EndSection. In each banner image, GetImageFunction is called. Using GetDisplayFunction at the end, the JavaScript is generated. The HTML then looks as follows: <html> <head> <title>Bannerpage</title> </head> <body> <div id="divQLyVKAQ3JtdV"> Bitte warten Sie, während die Seite geladen wird. ... </div> <div id="divoFkEnsWByT" STYLE="display:None;"> <p>Dieser Content wird erst nach dem Banner sichtbar - inklusive dem Banner.</p> <img src="url removed" alt="" onload="setqBv4nJ7uobMWXV2()" > </div> <div id="divQi3jesvMdf" STYLE="display:None;"> <p>Weiterer Text, nur als Demo gedacht.</p> </div> <SCRIPT LANGUAGE=JavaScript> <!-- var varKBKozSWZPk=1; function setqBv4nJ7uobMWXV2() { varKBKozSWZPk--; if (0 == varKBKozSWZPk) { document.all.divQLyVKAQ3JtdV.style.display = "none"; document.all.divoFkEnsWByT.style.display = ""; document.all.divQi3jesvMdf.style.display = ""; } } //--> </SCRIPT> </body> </html> With each request of the page the IDs of the DIV tags, the function name and the variable storing the number of images change. Mixed with a number of content sections this is a tough one to crack for banner blockers. ConclusionThe script presented of course isn't flawless - the lengths of the names of the DIV tags, variables and function should change randomly. One problem, however, cannot be solved by this script, even with the cleverest modifications: the banner blocker sends a placeholder image instead of the banner ad. Downloading the CodeClick here to start the download.
©2000-2004 AspHeute.com |