-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Separate adblock detection logic from adblock ask and record in `Metr…
…ics` (#11400)
- Loading branch information
Showing
4 changed files
with
128 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
// cache the promise so we only make the requests once | ||
let detectByRequests: Promise<boolean> | undefined; | ||
|
||
/** | ||
* Make a HEAD request to a URL that is typically blocked by ad-blockers | ||
*/ | ||
const requestDoubleclick = async (timeoutMs: number) => { | ||
try { | ||
const response = await fetch('https://www3.doubleclick.net', { | ||
method: 'HEAD', | ||
mode: 'no-cors', | ||
cache: 'no-store', | ||
signal: AbortSignal.timeout(timeoutMs), | ||
}); | ||
|
||
// A redirect is another clue we may be being ad-blocked | ||
if (response.redirected) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} catch (err) { | ||
return false; | ||
} | ||
}; | ||
|
||
/** | ||
* Make a HEAD request to a URL that should succeed, even when using an | ||
* ad-blocker | ||
*/ | ||
const requestGuardian = async (timeoutMs: number) => { | ||
try { | ||
await fetch('https://www.theguardian.com', { | ||
method: 'HEAD', | ||
mode: 'no-cors', | ||
cache: 'no-store', | ||
signal: AbortSignal.timeout(timeoutMs), | ||
}); | ||
return true; | ||
} catch (err) { | ||
return false; | ||
} | ||
}; | ||
|
||
/** | ||
* Attempt to detect presence of an ad-blocker | ||
* | ||
* This implementation of this is likely to be tweaked before launching the test | ||
* proper | ||
*/ | ||
export const detectByRequestsOnce = async (): Promise<boolean> => { | ||
if (detectByRequests) { | ||
return detectByRequests; | ||
} | ||
detectByRequests = Promise.all([ | ||
requestDoubleclick(1000), | ||
/** | ||
* We set this request with a much smaller timeout than the one we | ||
* expect to be ad-blocked. This should reduce the chance that request | ||
* fails and this one succeeds due to poor network connectivity | ||
*/ | ||
requestGuardian(250), | ||
]).then( | ||
([doubleclickSuccess, guardianSuccess]) => | ||
!doubleclickSuccess && guardianSuccess, | ||
); | ||
|
||
return detectByRequests; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { getConsentFor, onConsentChange } from '@guardian/libs'; | ||
import { useEffect, useState } from 'react'; | ||
import { detectByRequestsOnce } from './detect-adblock'; | ||
|
||
export const useDetectAdBlock = (): boolean => { | ||
const [adBlockerDetected, setAdBlockerDetected] = useState<boolean>(false); | ||
const [hasConsentForGoogletag, setHasConsentForGoogletag] = useState(false); | ||
|
||
useEffect(() => { | ||
onConsentChange((consentState) => { | ||
if (consentState.tcfv2) { | ||
return setHasConsentForGoogletag( | ||
getConsentFor('googletag', consentState), | ||
); | ||
} | ||
setHasConsentForGoogletag(true); | ||
}); | ||
}, []); | ||
|
||
useEffect(() => { | ||
const makeRequest = async () => { | ||
if (hasConsentForGoogletag) { | ||
const detectByRequests = await detectByRequestsOnce(); | ||
console.log('AdBlocker detected:', detectByRequests); | ||
setAdBlockerDetected(detectByRequests); | ||
} | ||
}; | ||
void makeRequest(); | ||
}, [hasConsentForGoogletag]); | ||
|
||
return adBlockerDetected; | ||
}; |