我正在尝试检测 AdBlock plus 是否在 Firefox 中运行,它不需要 100% 的时间工作,但我至少想禁用 Firefox 和 chrome 附带的内置广告拦截器。
看起来最有希望的解决方案来自这个blockAdBlock包。他们展示了一个有效的示例,但它需要操作主索引.html文件。我正在使用 Gatsby,它并不能真正让您访问.html文件,因此我想检测我的组件中的广告拦截器。
他们的 blockadblock.js 文件中的代码是一个 IIFE,我不太了解它,但我理解得足够多,知道它在创建时被调用。
如果我只是从该文件复制粘贴代码并将其放在我的组件中,然后尝试检查 adBlocker,看起来块广告块永远不会未定义
const BAB = (function(window) {...})(window);
if (typeof blockAdBlock === 'undefined'){ //Always true
alert('works')
canRunAds = false
}
如果他们的例子有效,我觉得我应该能够从中得到一些工作。
<小时 />我见过的大多数解决方案
我见过的每个常见答案都使用诸如放入div之类的东西,看起来像
<div id="ad-container">
<img src="../ad/ad.png" id="ad">
</div>
然后使用一些JavaScript来检查"ad-container"的高度是否>1。我的div 名称如"广告容器"(或广告、广告拦截、广告横幅(未被广告拦截器删除,因此此方法有问题。
FuckAdBlock/BlockAdBlock 库通过模拟 AdBlockers 已知会阻止的模式(特别是过滤的 CSS 类(并检查它是否被阻止来工作。 (您可以通过分析广告拦截器模式并将其嵌入到页面中来做类似的事情(。
使用FuckAdBlock项目示例。通过注入脚本标记在运行时从 cdnjs 动态加载脚本:
// Function called if AdBlock is not detected
function adBlockNotDetected() {
alert('AdBlock is not enabled');
}
// Function called if AdBlock is detected
function adBlockDetected() {
alert('AdBlock is enabled');
}
// We look at whether FuckAdBlock already exists.
if(typeof fuckAdBlock !== 'undefined' || typeof FuckAdBlock !== 'undefined') {
// If this is the case, it means that something tries to usurp are identity
// So, considering that it is a detection
adBlockDetected();
} else {
// Otherwise, you import the script FuckAdBlock
var importFAB = document.createElement('script');
importFAB.onload = function() {
// If all goes well, we configure FuckAdBlock
fuckAdBlock.onDetected(adBlockDetected)
fuckAdBlock.onNotDetected(adBlockNotDetected);
};
importFAB.onerror = function() {
// If the script does not load (blocked, integrity error, ...)
// Then a detection is triggered
adBlockDetected();
};
importFAB.integrity = 'sha256-xjwKUY/NgkPjZZBOtOxRYtK20GaqTwUCf7WYCJ1z69w=';
importFAB.crossOrigin = 'anonymous';
importFAB.src = 'https://cdnjs.cloudflare.com/ajax/libs/fuckadblock/3.2.1/fuckadblock.min.js';
document.head.appendChild(importFAB);
}
使用BlockAdblock项目示例。包括来自cdnjs CDN的blockadblock.js:
// Function called if AdBlock is not detected
function adBlockNotDetected() {
alert('AdBlock is not enabled');
}
// Function called if AdBlock is detected
function adBlockDetected() {
alert('AdBlock is enabled');
}
// Recommended audit because AdBlock lock the file 'blockadblock.js'
// If the file is not called, the variable does not exist 'blockAdBlock'
// This means that AdBlock is present
if(typeof blockAdBlock === 'undefined') {
adBlockDetected();
} else {
blockAdBlock.onDetected(adBlockDetected);
blockAdBlock.onNotDetected(adBlockNotDetected);
// and|or
blockAdBlock.on(true, adBlockDetected);
blockAdBlock.on(false, adBlockNotDetected);
// and|or
blockAdBlock.on(true, adBlockDetected).onNotDetected(adBlockNotDetected);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/blockadblock/3.2.1/blockadblock.min.js" integrity="sha512-EFY34xQ/AKRSb4EfjeRCO1TXnLuDQrYlo3BVId+DU8J4BiKUezCWK93bUlXTkEf4a8rMRroouaPXHnq/WTK4pA==" crossorigin="anonymous"></script>
只是检查 iframe 的高度对我有用:
(当 iframe 的大小发生变化时,使用 ResizeObserver 挂钩。 setTimeout 在 5 秒后因缺乏 ResizeObserver 支持而超时。
注意:检查上面链接中的支持表和/或使用 ResizeObserver.
eg:iOS Safari 只有 13.4+,这可能不是许多人可接受的支持级别
fn = () => document.querySelector('.jellyWidget').clientHeight > 0 || alert('blocked')
fn()
setTimeout(fn,5000)
typeof ResizeObserver!=='undefined' &&
new ResizeObserver(fn).observe(document.querySelector('.jellyWidget'))
fn = () => document.querySelector('.jellyWidget').clientHeight > 0 || alert('blocked')
fn()
setTimeout(fn,5000)
typeof ResizeObserver!=='undefined' &&
new ResizeObserver(fn).observe(document.querySelector('.jellyWidget'))
<iframe src="//rcm-na.amazon-adsystem.com/e/cm?o=15&p=14&l=ur1&category=biss&banner=05GNDH2E5A6MQH5KAZ02&f=ifr&linkID=3980418b7a5cc00e6f0e0fac51cf69f9&t=suddenlysas06-20&tracking_id=suddenlysas06-20" scrolling="no" style="border: medium none;" class="jellyWidget undefined" width="160" height="600">#document<head><script type="text/javascript">
/**
* Created by pedapav on 4/1/15.
*
* Tracking utilities to be used by client side rendering templates.
*/
window["trackingUtils"] = function(regionInt, foresterChannelUrlPrefix, impressionRecorderPrefix, pixelUrl,
clickUrl, impressionToken, slotNum, subtag, ABPPixelURL, disableABPCheck, AESPixelUrl) {
var that = {},
refMatch = new RegExp("/(ref=[\w]+)/?", "i"),
TRANSIT_ID_KEY = "assocPayloadId",
encodeStr = function (b) {
return b && encodeURIComponent(b).replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
},
rawRefURL = (function() {
var alink = document.createElement("a");
alink.href = (window.location !== window.parent.location) ? document.referrer : document.location;
// on IE, path name does not begin with a '/' - append it.
// on IE, 'host' property includes the port even if it is standard port 80/443
// but on IE, document.location.href does not include standard ports
// so we have to remove them before forming 'ref-refUrl'
return alink.protocol + "//" + alink.hostname +
((alink.port === "" || alink.port === "80" || alink.port === "443") ? "" : (":" + alink.port)) +
(alink.pathname.indexOf("/") !== 0 ? ("/" + alink.pathname) : alink.pathname);
}()),
refRefURL = (function() {
return encodeStr(rawRefURL);
}()),
addQueryParameter = function(linkElem, paramName, paramValue, overwrite) {
if(typeof paramValue === "string" && paramValue !== "") {
if (linkElem.search === "") {
linkElem.search = "?" + paramName + "=" + paramValue;
} else if(!linkElem.search.match(new RegExp("[?&]" + paramName + "="))) {
linkElem.search = linkElem.search.replace(/?/, "?" + paramName + "=" + paramValue + "&");
} else if(overwrite) {
// query parameter already present - overwrite it, if forced
linkElem.search = linkElem.search.replace(new RegExp(paramName + "=([^&]*)"), paramName + "=" + paramValue);
}
}
return linkElem;
},
addQueryParameterStr = function(linkTarget, paramName, paramValue) {
if(typeof paramValue === "string" && paramValue !== "") {
if (!linkTarget.match(/?/)) {
linkTarget = linkTarget + "?" + paramName + "=" + paramValue;
} else if(!linkTarget.match(paramName)) {
linkTarget = linkTarget.replace(/?/, "?" + paramName + "=" + paramValue + "&");
}
}
return linkTarget;
},
getEffectiveSlotNum = function(localSlotNum) {
var finalSlotNum = (typeof slotNum !== "undefined") ? slotNum : 0;
if(typeof localSlotNum !== "undefined") finalSlotNum = localSlotNum;
return finalSlotNum;
};
that.addRefUrls = function (allLinks, linkId, linkCode, trackingId) {
var amazonLinkPattern = new RegExp("^http://.*(amazon|endless|myhabit|amazonwireless|javari|smallparts)\.(com|ca|co\.jp|de|fr|co\.uk|cn|it|es)/.*", "i"),
href, results, i;
for (i = 0; i < allLinks.length; i++) {
allLinks[i].rel = "nofollow";
href = String(allLinks[i].href);
if (results = href.match(amazonLinkPattern)) {
allLinks[i].href = that.addTrackingParameters(allLinks[i], linkId, linkCode, trackingId);
}
}
};
that.addRefRefUrl = function(linkElem) {
return addQueryParameter(linkElem, "ref-refURL", refRefURL);
};
that.getRefRefUrl = function() {
return refRefURL;
};
that.getRawRefUrl = function() {
return rawRefURL;
};
that.addSignature = function(linkElem, signature, signatureTimeStamp) {
return addQueryParameter(
addQueryParameter(linkElem, "sig", signature),
"sigts", signatureTimeStamp);
};
that.addLinkCode = function(linkElem, linkCode) {
return addQueryParameter(linkElem, "linkCode", linkCode);
};
that.addTrackingId = function(linkElem, trackingId) {
return addQueryParameter(linkElem, "tag", trackingId);
};
that.addLinkId = function(linkElem, linkId) {
return addQueryParameter(linkElem, "linkId", linkId);
};
that.addSubtag = function(linkElem, subtag) {
return addQueryParameter(linkElem, "ascsubtag", subtag);
};
that.addCreativeAsin = function(linkElem, adId){
return addQueryParameter(addQueryParameter(linkElem, "creativeASIN", adId), "adId", adId);
};
that.addAdType = function(linkElem, adType) {
return addQueryParameter(linkElem, 'adType', adType);
};
that.addAdMode = function(linkElem, adMode) {
return addQueryParameter(linkElem, 'adMode', adMode);
};
that.addAdFormat = function(linkElem, adFormat) {
return addQueryParameter(linkElem, 'adFormat', adFormat);
};
that.addImpressionTimestamp = function(linkElem, impressionTimestamp) {
if (typeof impressionTimestamp === "number") impressionTimestamp = impressionTimestamp.toString();
return addQueryParameter(linkElem, 'impressionTimestamp', impressionTimestamp);
};
that.convertToRedirectedUrl = function(linkElem, prefix, destParamName) {
var alink = document.createElement("a");
alink.setAttribute("href", prefix);
if(typeof destParamName !== "undefined") {
addQueryParameter(alink, destParamName, encodeStr(linkElem.getAttribute("href")), true);
} else {
alink.setAttribute("href", prefix + "/" + alink.getAttribute("href"));
}
linkElem.setAttribute("href", alink.getAttribute("href"));
return linkElem;
};
that.getImpressionToken = function() {
return impressionToken;
};
//we are using impressionToken as transitId right now,
//can be changed to GUID in future
that.generateTransitId = function() {
return that.getHashedImpressionToken();
};
that.getHashedImpressionToken = function(){
var pixelUrlParts = pixelUrl.split("/");
//pixelUrl is http://pixelurl.com/x/px/HASHEDIMPRESSIONTOKEN/
var hashedImpressionToken = pixelUrlParts[pixelUrlParts.length - 2]
return hashedImpressionToken;
};
that.getTransitId = function(){
if(typeof assoc_session_storage !== "undefined"){
var existingTransitId = assoc_session_storage.get(TRANSIT_ID_KEY);
return existingTransitId;
}
return null;
};
that.getClickUrl = function() {
return clickUrl;
};
that.addImpressionToken = function(linkElem, localSlotNum) {
var finalSlotNum = getEffectiveSlotNum(localSlotNum);
if(typeof impressionToken === "string" && impressionToken !== "") {
addQueryParameter(linkElem, "imprToken", impressionToken);
if(typeof finalSlotNum !== "undefined") addQueryParameter(linkElem, "slotNum", finalSlotNum);
}
return linkElem;
};
that.addImpressionTokenStr = function(url, localSlotNum) {
var finalSlotNum = getEffectiveSlotNum(localSlotNum);
if(typeof impressionToken === "string" && impressionToken !== "") {
url = addQueryParameterStr(url, "imprToken", impressionToken);
if(typeof finalSlotNum !== "undefined") url = addQueryParameterStr(url, "slotNum", finalSlotNum);
}
return url;
};
that.addTrackingParameters = function(linkElem, linkId, linkCode, trackingId, refMarker, creativeASIN, signature, signatureTimeStamp, adType, adMode, adFormat, impressionTimestamp) {
return that.addSignature(
that.addCreativeAsin(
that.addLinkId(
that.addTrackingId(
that.addSubtag(
that.addLinkCode(
that.addRefRefUrl(
that.addImpressionToken(
that.addRefMarker(
that.addAdType(
that.addAdMode(
that.addAdFormat(
that.addImpressionTimestamp(linkElem, impressionTimestamp),
adFormat),
adMode),
adType),
refMarker))),
linkCode),
subtag),
trackingId),
linkId),
creativeASIN),
signature, signatureTimeStamp
);
};
that.addRefMarker = function(linkElem, refMarker) {
var match, endsWithSlash = false;
if(typeof refMarker === "undefined") return linkElem;
if(match = linkElem.pathname.match(refMatch)) {
linkElem.pathname = linkElem.pathname.replace(match[1], "ref=" + refMarker);
} else {
endsWithSlash = (linkElem.pathname.charAt(linkElem.pathname.length - 1) === '/');
linkElem.pathname = linkElem.pathname + (endsWithSlash ? "" : "/") + "ref=" + refMarker;
}
return linkElem;
};
that.getRefMarker = function(linkElem) {
var match;
if(match = linkElem.pathname.match(refMatch)) {
return match[1].substr(4);
} else return undefined;
};
that.getCurrentURL = function(){
return (window.location !== window.parent.location) ? document.referrer : document.location.href;
}
that.makeForesterCall = function(data) {
var finalAAXPixelUrl = undefined, json;
if(typeof JSON !== 'undefined') json = JSON.stringify(data);
else if(typeof amzn_assoc_utils !== "undefined" && typeof amzn_assoc_utils["stringify"] === "function") json = amzn_assoc_utils.stringify(data);
else return;
if(typeof pixelUrl === "string") {
finalAAXPixelUrl = pixelUrl + "?assoc_payload=" + encodeURIComponent(json);
that.generateImage(finalAAXPixelUrl);
}
};
that.recordImpression = function(linkCode, trackingId, data, skipIRCall, slotNum) {
data["linkCode"] = linkCode;
data["trackingId"] = trackingId;
data["refUrl"] = that.getCurrentURL();
if(disableABPCheck || !ABPPixelURL) {
that.makeForesterCall(data);
} else {
that.addABPFlag(data, that.makeForesterCall);
}
};
that.createAssocPayload = function(data, linkCode, trackingId, refUrl){
data["linkCode"] = linkCode;
data["trackingId"] = trackingId;
data["refUrl"] = refUrl;
var stringifiedData = "";
if(typeof amzn_assoc_utils !== "undefined" && typeof amzn_assoc_utils["stringify"] === "function")
stringifiedData = amzn_assoc_utils.stringify(data);
return stringifiedData;
}
that.recordAESImpression = function(linkCode, trackingId, data){
if(typeof AESPixelUrl === "string") {
var assocPayload = that.createAssocPayload(data, linkCode, trackingId, that.getCurrentURL());
var hashedImpressionToken = that.getHashedImpressionToken();
var finalAESPixelUrl = AESPixelUrl + hashedImpressionToken+"/pixel?assoc_payload=" + encodeURIComponent(assocPayload);
that.generateImage(finalAESPixelUrl);
}
};
that.recordTransit = function(){
//if transitId is not present or blog has utm_param in url, set new transitId
if(!(that.getTransitId()) || that.isUTMParamPresentInUrl(that.getCurrentURL())){
assoc_session_storage.set(TRANSIT_ID_KEY, that.generateTransitId());
}
}
that.isUTMParamPresentInUrl = function(url){
var utmParamExists = url.match(/utm_source=/i);
return (utmParamExists !== null);
}
that.addAAXClickUrls = function(links){
var aaxClickUrl, i, href;
//convert all given links with AAX click urls
if(typeof links === 'undefined' || typeof clickUrl === 'undefined') return;
for (i = 0; i < links.length; i++) {
href = String(links[i].href);
if(href.indexOf(clickUrl) < 0) {
aaxClickUrl = clickUrl + href;
links[i].href = aaxClickUrl;
}
}
};
that.addAAXClickUrl = function(url){
//append given url with AAX click url
if(typeof url === 'undefined' || url.indexOf(clickUrl) === 0) return url;
return clickUrl + url;
};
that.updateLinks = function(links, updaterFunc) {
var i, href;
if(typeof updaterFunc !== "function") return;
for(i = 0; i < links.length; i++) {
href = String(links[i].href);
links[i].href = updaterFunc(href);
}
};
that.elementInViewPort = function(el) {
var rect = el.getBoundingClientRect(),
inViewPort = (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth)
);
return {
"posX": rect.left + window.pageXOffset,
"posY": rect.top + window.pageYOffset,
"inViewPort": inViewPort
};
};
that.recordViewability = function(slotNum, aboveTheFold, topPos, leftPos){
if(typeof pixelUrl === "string") {
var payload = that.createViewbilityPayload(slotNum, aboveTheFold, topPos, leftPos);
var finalAAXPixelUrl = pixelUrl + payload + "&cb=" + (new Date()).getTime();
that.generateImage(finalAAXPixelUrl);
}
};
that.recordAESViewability = function(slotNum, aboveTheFold, topPos, leftPos){
if(typeof AESPixelUrl === "string") {
var payload = that.createViewbilityPayload(slotNum, aboveTheFold, topPos, leftPos);
var hashedImpressionToken = that.getHashedImpressionToken();
var encodedPayload = encodeURIComponent(payload);
var finalAESPixelUrl = AESPixelUrl + hashedImpressionToken + "/pixel/"+encodedPayload
+ "&cb=" + (new Date()).getTime();
that.generateImage(finalAESPixelUrl);
}
};
that.createViewbilityPayload = function(slotNum, aboveTheFold, topPos, leftPos){
var viewbilityAttr = {};
if(typeof aboveTheFold !== "undefined") viewbilityAttr["above_the_fold"] = aboveTheFold;
if(typeof topPos !== "undefined") viewbilityAttr["topPos"] = topPos;
if(typeof leftPos !== "undefined") viewbilityAttr["leftPos"] = leftPos;
if(typeof slotNum !== "undefined"){
//handling case when only slotnum is passed
if (Object.keys(viewbilityAttr).length === 0)
viewbilityAttr["viewable"] = true;
viewbilityAttr["slotNum"] = slotNum;
}
var stringifiedData = "";
if(typeof amzn_assoc_utils !== "undefined" && typeof amzn_assoc_utils["stringify"] === "function")
stringifiedData = amzn_assoc_utils.stringify({"adViewability":[viewbilityAttr]});
return stringifiedData;
};
that.generateImage = function(imageSrc){
if(typeof imageSrc !== "undefined")
(new Image()).src = imageSrc;
};
that.addABPFlag = function(data, callback) {
var detected = false,
checksRemain = 2,
img1 = document.body ? document.body.appendChild(new Image()) : new Image(),
img2 = document.body ? document.body.appendChild(new Image()) : new Image(),
error1 = false,
error2 = false,
random = Math.random() * 11,
px = ABPPixelURL + "?ch=*&rn=*",
beforeCheck = function(callback, timeout) {
if (checksRemain === 0 || timeout > 1E3) {
data.supplySideMetadata = {
ABPInstalled: checksRemain === 0 && detected
};
callback(data);
} else {
setTimeout(function() {
beforeCheck(callback, timeout * 2);
}, timeout * 2);
}
},
checkImages = function() {
if(--checksRemain)
return;
detected = !error1 && error2;
};
img1.style.display = "none";
img2.style.display = "none";
img1.onload = checkImages;
img1.onerror = function() {
error1 = true;
checkImages();
};
img1.src = px.replace(/*/, 1).replace(/*/, random);
img2.onload = checkImages;
img2.onerror = function() {
error2 = true;
checkImages();
};
img2.src = px.replace(/*/, 2).replace(/*/, random);
beforeCheck(callback, 250);
};
return that;
};
if(typeof amzn_assoc_utils === "undefined") {
amzn_assoc_utils = {};
}
</head>
<body style="margin-bottom: 0px; margin-top: 0px;" class="vsc-initialized" marginwidth="0">
<div id="amznBanners_assoc_banner_placement_default_${slotNum}_div">
<img id="amznBanners_assoc_banner_placement_default_${slotNum}_img" usemap="#amznBanners_assoc_banner_placement_default_${slotNum}_boxmap" src="https://images-na.ssl-images-amazon.com/images/G/15/img15/biss/Associates/24569-CA-BISS-21Aug-frassco_160x600._V313078032_.png">
<map name="amznBanners_assoc_banner_placement_default_${slotNum}_boxmap">
<area id="amznBanners_assoc_banner_placement_default_${slotNum}_privacybox" shape="rect" coords="(0,588,160,600)" href="http://rcm-na.amazon-adsystem.com/e/cm/privacy-policy.html?o=15" target="_top" rel="nofollow">
<area id="amznBanners_assoc_banner_placement_default_${slotNum}_a" shape="rect" coords="0,0,10000,10000" href="https://www.amazon.ca/b?tag=suddenlysas06-20&linkCode=ur1&node=11076213011" target="_top" rel="nofollow">
</map>
</div>
<script type="text/javascript">
amzn_assoc_ad_spec.isIframe = true;
amzn_assoc_ad_spec.linkCode = "ur1";
window.amznBannerAd(amzn_assoc_ad_spec).init();
var amazon_assoc_ir_f_call_associates_ads = function(map) {
var logTypeStr = "", foresterURL, json;
if(typeof JSON !== 'undefined') json = JSON.stringify(map);
else if(typeof amzn_assoc_utils !== 'undefined') json = amzn_assoc_utils.stringify(map);
else return;
if(typeof map.logType !== "undefined") logTypeStr = "&logType=" + map.logType;
// forester URLs are of format //<end_point>/<api_version>/<channel_id>/<channel_version>/<OPERATION>/
// Depending on operation, we either pass the data in the URI or we pass them as query parameters
// if operation is OP, data must be in query parameters while if operation is TOP,
// data must be in the URI itself
foresterURL = "//fls-na.amazon-adsystem.com/1/associates-ads/1/OP/r/json";
foresterURL = foresterURL + "?cb=" + (new Date()).getTime() + logTypeStr + "&p=" + encodeURIComponent(json);
(new Image()).src = foresterURL;
};
var amazon_assoc_ir_f_call = amazon_assoc_ir_f_call_associates_ads;
</script>
</body></iframe>
注意:这不会检测到普通的可见性隐藏(他们使用注入的样式使它们不可见而不是阻塞和折叠(或更复杂的阻止,如果(可能是"何时"的问题(这演变成(反(广告拦截器军备竞赛,最终会发生。 这是一场你不会赢的比赛,可能会引起用户的愤怒。 只是对它保持"友善"应该希望主要防止这种情况,选择主要是"不显眼"的基于文本的广告和通过电子邮件发送广告拦截器团队将您列入不显眼的名单是另一种选择.
但是,我强调这一点,这是您的决定。
我的功能性广告拦截器
const _handleNavigation = async () => {
dispatch('RESET_CONTEXT');
try {
const url = `https://ads.google.com?=${new Date().getTime()}`;
await axios.get(url);
router.push('/post');
} catch (error) {
enqueueSnackbar(`Please disable your ad blocker to post`, snackbar.ERROR_TOP_CENTER);
}
};