如何使用 JavaScript 檢測用戶是否啓用三方 Cookie ?

大家好,我是 ConardLi

今天繼續來聊  CookieChrome 已經在 1.4 號開啓了三方 Cookie1% 禁用灰度:

不少小夥伴反饋已經命中了這個灰度,因爲時間比較急,很多網站來不及改造,很多網站的正常功能在這個灰度策略下受到了影響。

在前面的文章中我們提到,對於一些還沒來得及改造完的網站,Chrome 提供了一種便捷的方式來讓命中灰度的用戶手動關閉這個策略:

這個開關點擊後可以允許指定域名繼續使用三方 Cookie ,但是這個期限只有 90 天。

所以,如果大家的網站最近沒有時間進行這些改造,大家可以在運行時來提示用戶手動關閉三方 Cookie 的禁用策略。

那麼問題來了,並不是所有用戶都命中了這個策略,當前只有 1% ,我們可能給所有的用戶都添加這個提示,所以我們如何在運行時檢測用戶是否命中了三方 Cookie 的灰度策略呢?

function checkCookie(){
    var cookieEnabled = navigator.cookieEnabled;
    if (!cookieEnabled){ 
        document.cookie = "testcookie"; 
        cookieEnabled = document.cookie.indexOf("testcookie")!=-1;
    }
    return cookieEnabled || showCookieFail();
}

function showCookieFail(){
  // do something here
}

checkCookie();

上面的代碼片段可用於檢查 Cookie 是否啓用,但是對三方 Cookie 的檢查就無能爲力了,三方 Cookie 禁用的情況下還是會返回 true

我能想到的並且一直有效的方法就是添加一個外部(三方)的 iFrame,讓它來檢測 iFrame 內部是否可以訪問到 Cookie,並且會將 Cookie 的可用狀態通知給父應用。

雖然這聽起來挺奇怪的,我們好像無法直接通過 iFrame 調用父頁面的功能。但是我們可以使用 Message Event 來進行父子應用之間的通信,通過這個我們可以基於 URL 向其他瀏覽器發送消息,在我們現在這種情況下,我們可以從 iFrame 向可能在不同域上的父應用發送消息。

首先,我們在 iFrame 內添加一個立即執行函數。在這個函數中,我們添加一個消息事件監聽器,這個監聽器會在從父級應用程序調用時觸發。當被調用時,它首先會驗證請求,然後調用 checkCookiesEnable 函數來檢查 Cookie 的狀態並返回結果。然後,我們通過 parent.postMessage() 方法向父應用發送一條消息;在 iFrame 中,parent 是一個隱含的對象。

<!doctype html>
<html>
<head>
</head>
<body>
    <script>
        const checkCookiesEnable = () ={
            let isCookieEnabled = (window.navigator.cookieEnabled) ? true : false;
            if (typeof window.navigator.cookieEnabled == "undefined" && !isCookieEnabled) {
                // 嘗試設置一個測試cookie
                document.cookie = "testcookie";
                // 檢查cookie是否已設置
                isCookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false;
            }

            return isCookieEnabled;
        }

        // 監聽消息事件,響應從父窗口傳來的消息
        (function () {
            window.addEventListener('message'event ={
                try {
                    let data = JSON.parse(event.data)
                    if (data['test'] !== 'cookie')
                        return
                    let result = checkCookiesEnable();
                    // 將結果通過消息事件發送到父窗口
                    parent.postMessage(JSON.stringify({
                        'result': result
                    }), event.origin);
                }
                catch (e) {
                    console.error(e)
                }
            });
        })();
    </script>
</body>
</html>

在這裏,我們將添加一個消息事件處理程序,然後在插入任何第三方腳本之前插入我們的 iFrame。一旦 iFrame 加載完畢,我們將通過 frame.contentWindow 對象向我們的 iFrame 發送 postMessage,使用 "*" 允許 postMessage 任何來源(不同的域)。

然後,iFrame 內部的函數檢查iFrameCookie 狀態併發送一個消息,該消息被我們的 messagehandler 攔截。檢查消息是否由 iFrame 發送,事件現在將保存來自 iFrame 內的 checkCookieEnable 函數結果的響應。

下面是一個示例函數,它接受 iframeUri 和一個回調函數,在收到結果後將被調用。

const cookieTest = (iFrameUri, callBack) ={
    let messageHandler = (event) ={
        // 在這裏檢查受信任的來源
        const data = JSON.parse(event.data);
        callBack(data['result']);
        window.removeEventListener('message', messageHandler);
        document.body.removeChild(frame);
    };

    // 監聽消息事件,響應從 iframe 窗口傳來的消息
    window.addEventListener('message', messageHandler);

    // 創建並添加一個隱藏的 iframe 元素
    const frame = document.createElement('iframe');
    frame.src = iFrameUri;
    frame.sandbox = "allow-scripts allow-same-origin";
    frame.style = `display:none`;
    frame.onload = (e) ={
        // 向 iframe 發送一個消息,請求檢查 cookie 的情況
        frame.contentWindow.postMessage(JSON.stringify({ 'test''cookie' })'*');
    };

    document.body.appendChild(frame);
};

export default cookieTest;

你可以直接把上面的代碼片段放入你的網站中,並提供一個回調函數來爲用戶呈現適當的消息。

現在,我們可以成功地在運行時檢測到用戶的第三方 Cookie 是否已啓用了!

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/OjpzmJDII1jy3ZSuc6eOGA