广告拦截检测,又称Adblock Plus

48

在谷歌和 Stackoverflow 上搜索了几个小时后,我无法找到解决方案。 我的目标是当前先检测Adblock Plus并显示一个简单的消息。

我想做的是检测 Adblock Plus,不使用JavaScript文件或jQuery。 大多数 Adblock Plus 检测脚本都使用一个名为 "show_ads.js" 的文件,并在其自己的域上托管,其中有一行将其设置为 "adblock = false;"

使用 JavaScript 文件的问题在于用户可以将该 JavaScript 文件加入白名单,那么它就不再被检测。我要找的是一个直接加载到 HTML 中的 JavaScript,能够检测是否有人使用广告拦截软件,而不需要使用文件。

以下是示例:

<script type="text/javascript">
 // line of code that detects if using ad blocker

 if so display message
 </script>

这样做的原因是没有任何广告拦截器可以将您服务器上的JavaScript文件列入白名单。是的,我知道还有其他方法可以通过NoScript插件来绕过此问题,但我已经有了解决方案。我有一个很棒的想法,它从未被尝试过,而且一旦我完成它,广告拦截器就无法阻止它。

非常感谢任何建议和示例。


2
我开源了我的AdBlock检测器。它在这里:http://esd.io/blog/detecting-adblock-javascript.html - Eli
@Eli 我发现无论如何他们都可以阻止反广告拦截器,即使你使用来自不同域的脚本,甚至是通过你的网站加载的来自不同域的iframe。最好且唯一的方法是让你的域名重定向到一个免费的域名,该域名进行快速检查并发送回get请求。唯一的问题是他们必须关闭广告拦截器,因为你每隔几天更改的随机域名没有被列入白名单,即使他们在你的正常域上这样做。 - chillers
@ELI 现在关于你检测广告拦截器的方法,它会起作用,因为他们不会将其添加到白名单中,因为你没有阻止用户访问你的网站。我正在寻找像 http://antiblock.org/ 这样的反广告拦截器,它非常好用,特别是 PHP 版本。唯一的问题是,一旦有人向 easy list 报告你,他们就会创建一些规则来绕过它。我已经创建了最好的反广告拦截器,但需要用户完全关闭广告拦截器才能访问该网站。我还没有找到 easy list 无法屏蔽并仍然允许用户将域名加入白名单的解决方案。 - chillers
1
@Eli - 你的代码未能检测到我启用的广告拦截器。 - Lajos Mészáros
@Eli,感谢您发布代码,但目前它无法工作。请查看我上传的屏幕截图:https://s12.postimg.org/t4xlpr871/Capture.png - sm535
我不明白为什么有人想要在这个问题上提供帮助。 - Tanveer Badar
15个回答

76

您无需使用插件来检测广告拦截器,只需要使用以下代码:

<script type="text/javascript">
    var adblock = true;
</script>
<script type="text/javascript" src="adframe.js"></script>
<script type="text/javascript">
    if(adblock) {
          //adblock is installed and enabled on this site :-D
    }
</script>

adframe.js的内容:

adblock = false;

更新: Adblock Plus 根据其已有的模式阻止特定请求或隐藏特定元素。其中一个模式在 patterns.ini 中如下:

[Filter]
text=/adframe.
hitCount=843
lastHit=1456391595626

阻止任何URL中含有/adframe.的内容。 更新于2018年8月25日 Adblock Plus已更改其查找列表和阻止广告的方式。 它有一堆称为订阅的列表用于阻止。 例如,默认列表如下:

https://easylist-downloads.adblockplus.org/easylist.txt

你可以使用此文件中的规则来查找要使用的文件名。例如,你可以使用seo-ads.js
开发人员注意:由于某种原因,我无法在本地环境中阻止ABP阻止这些文件。
顺便说一句,ABP是我最喜欢的广告拦截器 :-D

这取决于AdBlock默认情况下始终阻止adframe.js - Ken Sharp
1
@ken 是的,它是这样的。但这是ABP的默认行为。您可以查看 patterns.ini 以获取更多模式。 - undone
这是一个不错的部分解决方案。还有其他的方案。我正在野外测试一堆方案,等我满意了就会分享。 - Ken Sharp
我刚意识到我没有使用相同的名称。我发现ABP也因为显而易见的原因阻止了advert.js,但我看到你已经添加了如何找到列表的方法。 - Ken Sharp
好的,我已经为Analytics设计了一个解决方法:http://kennystechtalk.blogspot.com/2016/03/adblockanalytics.html 这比绕过ABP所需的更复杂。 - Ken Sharp
显示剩余2条评论

19

25
这就是为什么存在“BlockAdBlock”分支的原因:https://github.com/sitexw/BlockAdBlock - SiteXw
我不太明白如何安装这个脚本。它能在普通的HTML网站上工作吗?还是我需要那个叫做“Bower”的东西? - Gabriel
@FrostyFrog 这里有一个完整的在线示例:http://jsfiddle.net/sitexw/vz4u101w/ - SiteXw
3
因为回答依赖于链接,而整个脚本可以在简短的回答中解释,所以被给予负面评价。 - user1596138
我点击了你在线的完整示例(jsfiddle),但是我得到了“检测到AdBlock: no”的提示。然而,我使用的是Firefox的AdBlock插件(确切的名称是AdBlock)。它已经开启,并且所有设置都是默认的(只有几个网站被加入白名单,但jsfiddle不在其中)。 - Dalibor

10

在实践中,我看到的做法是在广告后面使用背景图像。如果adblock没有激活,广告将显示在背景图像上方(这使得背景图像不可见)。如果adblock被激活,广告将被屏蔽,用户将看到背景图像。

<div id="ad-container">
  <img src="../ad/ad.png" id="ad">
</div>

使用CSS:

#ad-container {
  background-image: url( http://domain.com/pleasedonotuseadblocker.png );
  height: 200px;
  width: 200px;
}

#ad {
  height: 200px;
  width: 200px;
}

我需要它至少是JavaScript,因为我会添加代码以获取其他选项。这对于一个网站来说很好,但我计划在多个网站上使用此代码。 - chillers
4
提高用户意识,告知网站使用广告来资助网站的方式比强制显示广告更为有效,即使人们使用广告拦截工具。当一个网站采用强制广告方式时,还有更好的替代方案。我只是使用广告拦截工具,因为每个网站都使用令人讨厌的广告。如果我真的想支持某个网站,我不介意将其加入白名单。 - Sumurai8
1
@chiller:增加广告数量,这样对于那些喜欢广告的用户,你可以平衡那些不喜欢广告的用户。听起来像是简单的数学问题。 - hakre
2
@hakre,很抱歉你不能靠广告谋生。我相信互联网应该自由和开放,但是当你的唯一收入来源被人屏蔽以支付服务器费用等时,只是坐在那里也很难受。 - chillers
2
当然,我只访问内容网站,而不是广告网站。如果网站所有者觉得需要广告,那是他们的选择。我选择安装广告拦截器,如果网站抱怨,我甚至不再访问它们。某个地方已经越过了界限,我的底线是当网站恳求你禁用广告拦截器时。你的情况可能会有所不同。广告只是信息社会中的污染物,它利用了人类的自然兴趣。这是反社会和有毒的行为。 - hakre
显示剩余6条评论

6
如果你想在AdBlock激活时仍然显示广告,你需要了解AdBlock能够做什么。
1. AdBlock可以阻止资源加载。 2. AdBlock可以隐藏DOM中的特定元素。
尽管AdBlock可以修改CSS,但我找不到除了隐藏和折叠元素之外的任何文档。
那么,您应该如何比AdBlock更“聪明”呢?
您可以以永远不会“匹配”的方式伪装您的请求(例如,http://domain.com/ae9a70e0a.png,其中图像名称每次都是随机的,没有共同的前缀)。据我所知,AdBlock规则不能包含正则表达式。规则要么匹配零个广告,要么匹配太多资源。可以在服务器上重写此类URL以指向您的广告。
但是,尽管AdBlock可能无法阻止您的广告加载,但它仍然可能将其隐藏起来。没有真正的方法可以避免这种情况。总会有一个聪明的CSS选择器,只会选择您的元素。但是,您可以添加具有内容的背景图像。这对于广告(不可点击)没有用处,但可能有助于您显示其他消息。缺点是,如果有人决定阻止那个讨厌的背景图像,它也会隐藏您的内容。
至于脚本,您可以使用ajax请求加载广告。我认为(但无法测试),如果资源无法加载(因为被阻止),它将会出现错误。(在jQuery中$.ajax( request ).error( function() { ... } );或在常规JavaScript中使用等效项)。您可以将其包含在文档本身中,而不是外部资源中,以确保它始终运行(如果启用了JavaScript)。即使这样,您也不能确定“您所做的任何其他事情”是否会被可见地显示。作为最后一招,您可以使用window.alert(...)。如果您使用它,假设在3页内,您的访问者永远不会回来。
我能想到的另一种方法是创建一个WebSocket到服务器(据我所知,这不可能被AdBlock阻止)。在服务器端,您需要检查当加载某个页面时是否未加载广告页面。可以通过套接字发送此信息,该信息可用于您的脚本执行“某些操作”。但是,这听起来非常复杂,并且是“只”检测AdBlock的脚本的重大开销。

我很感激你的回答,也不会因为检测广告拦截而抨击我,这对我很有帮助。我找到了一种简单的方法来检测它,它不使用任何像.js或img之类的链接。因此,广告拦截无法将链接列入白名单以绕过它。现在正在寻找防止div被列入白名单的解决方案。谢谢! - chillers
AdBlock 绝对支持正则表达式。 - Ken Sharp
请记住,这篇文章是三年前写的;我认为自定义规则语法仍然有一定限制。我无法从这里检查它现在是否具有完整的正则表达式支持。 - Sumurai8

4
一个简单的Ajax调用就能完成任务:
var xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function() {
  if( xmlhttp.readyState == XMLHttpRequest.DONE ){
    if( xmlhttp.status !== 404 ){
        console.log("Blocking ads")
    }else{
        console.log("Not blocking ads")
    }
  }
}
xmlhttp.open("GET", "/498100ffe815d700cd838d1/ads/showad.js", true)
xmlhttp.send()

甚至更好的是,无需HTTP开销:
var adBlockTester = document.createElement('div');
adBlockTester.innerHTML = '&nbsp;';
adBlockTester.className = 'adsbox';
document.body.appendChild(adBlockTester);
window.setTimeout(function() {
  if( adBlockTester.offsetHeight === 0 ){
    console.log("Blocking ads")
  }else{
    console.log("Not blocking ads")
  }
  document.body.removeChild(adBlockTester);
}, 60);

3
以下代码片段可以几乎检测到所有的广告拦截器。需要使用 jQuery

(function(){
    var bait = 'http://googleads.g.doubleclick.net/pagead/gen_204?id=wfocus&gqid=advertisment&advert=ads';
      $.ajax({ url: bait, dataType: "script"})
      .fail(function () { alert('ad blocked'); })
      .abort(function () { alert('ad blocked'); });
    })();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

它被包装在一个自执行的匿名函数中,以便它不会干扰站点上的其他变量或代码。

bait使用最流行的广告服务网络(Google的双倍点击),并包括一些由easylist和其他人使用的查询参数。

fail()abort()方法都是必需的,但只有其中之一会被调用。

不要将代码放在adblocker.js或类似文件中,因为这些文件名本身就会被阻止加载。要么内联它,要么将其包含在随机/任意文件名中,要么将其合并到主站点JS文件中。


这是最好的方法,非常类似于我的 - https://dev59.com/S2445IYBdhLWcg3wapvF#53036744 - zax

2
这里是检测广告拦截器的代码。你可以在这里了解代码的工作原理: 这里
function detect()
{
    //create a iframe. Append the iframe to the body. And then after 100ms check if their offsetHeight, display or visibility is set such a way that user cannot see them.
    //In the URL use the words specific to advertising so that Adblock can do string matching.
    var iframe = document.createElement("iframe");
    iframe.height = "1px";
    iframe.width = "1px";
    iframe.id = "ads-text-iframe";
    iframe.src = "http://domain.com/ads.html";

    document.body.appendChild(iframe);

    setTimeout(function()
               {
                   var iframe = document.getElementById("ads-text-iframe");
                   if(iframe.style.display == "none" || iframe.style.display == "hidden" || iframe.style.visibility == "hidden" || iframe.offsetHeight == 0)
                   {
                        alert("Adblock is blocking ads on this page");
                        iframe.remove();
                   }
                   else
                   {
                        alert("Adblock is not detecting ads on this page");
                        iframe.remove();
                   }
               }, 100);
}

2

简单易用的JavaScript/jQuery检测方法:

$('body').append('<div id="ad-container" style="position:absolute;"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=" id="ad"></div>');
var ad_container = $('body').children('#ad-container');
if(!ad_container.is(":visible")) {
  // Add your warning and/or adblock detection logic here.
}
ad_container.remove();

2
我发现最聪明和最简单的方法是: 1)在你的标记中的某个位置添加这段html代码,可能是在顶部。
<div id="bait" class="pub_300x250" style="color: #fff">.</div>

通常广告拦截器会检测到(pub_300x250)等大小的广告,如Easylist中所述,并将其阻止,这是由“诱饵”触发的。

2) 然后将此js代码添加到您的脚本文件中。

if (document.getElementById("bait").offsetHeight === 0) {
    // function code or alert (whatever) here.
   alert("Ad-Blocker DETECTED");
}

我们的脚本通过检查“bait” ID 来检测当前HTML中是否存在该标记。这对我在每个浏览器上的每个网站上使用 Adblock、AdBlock-Plus 和 uBlock Origin 都有效。请注意,保留HTML标签。

如果你这样做,你可以添加一些CSS来隐藏它:#bait { position: absolute; left: -5px; } - Emeric
是的,你可以这样做。但是正如你所看到的,div里面没有任何内容。因此不需要这样做,因为它只会占用空白点。但是如果你关心空间,那么你可以这样做。你可以通过绝对定位和左侧隐藏它。 :) - Arslan Ameer
你的颜色只能在白色背景下工作,但如果背景经常更改且没有绝对定位,那么根据您放置 div 的位置可能会出现问题! - Emeric
是的,你说得对。那就是我说的。而且,你可以将该 div 的颜色或背景颜色更改为透明。 - Arslan Ameer

1
在我的情况下,即使没有广告,ADB也会隐藏内容...(只是因为许多URL中存在“ad”单词,因为它是文章类型的缩略词...)但我注意到他们并没有删除内容,只是将display:none应用于body。所以作为额外的解决方案,我注意到将display:block !important应用于body可以防止Adblock Plus隐藏内容。
<body style="display: block !important;">
  <img src="url-containg-ad-ads-word.jpg" alt="you should see this anyway" >
</body> 

OP的请求是在脚本级别上进行识别。 - Raja Anbazhagan
这就是为什么我包含了“作为额外解决方案”的原因。 - Toni Michel Caubet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接