GuidesAnnouncementsCommunity Discussion
GuidesCommunity DiscussionAnnouncementsLog In
Guides

Local storage

Overview

As a Taboola publisher, make sure that your own JavaScript code follows best practice for client-side storage. Code that uses client-side storage 'blindly' may break on certain devices/browsers, preventing Taboola content from showing.

🚧

Loss of revenue

Code that uses client-side storage 'blindly' may break on certain devices/browsers.

These unhandled errors can prevent Taboola content from showing, resulting in a loss of revenue.

The problem

When working with client-side JavaScript, localStorage and sessionStorage are not guaranteed to be available.

Availability can depend on a variety of factors, including: the specific device and browser, user preferences, and whether the user is in private browsing mode.

To complicate matters, testing with the in operator can still return true, even when the object is not actually available:

An example

// Safari browser with cookies disabled

"localStorage" in window // returns true

window.localStorage // throws "SecurityError: The operation is insecure."

The solution

As best practice, we advise not accessing client-side storage directly. Instead, consider using a wrapper object, with a built-in 'fall-back' mechanism.

Sample code

The following sample code illustrates one possible approach. Feel free to adapt the code to your specific needs.

/*
* A wrapper object that allows you to use `localStorage` and `sessionStorage` safely.
* If the requested storage is available, it is used.
* Else, data is persisted to memory (until the user reloads the page).
*
* USAGE - EXAMPLES:
* -----------------
*
* Local Storage
* -------------
*
* var _localStorage = safeStorage.getStorage('local');
* _localStorage.setItem('myCat', 'foo');
* var cat = _localStorage.getItem('myCat');
* _localStorage.removeItem('myCat');
* _localStorage.clear();
*
* Session Storage
* ---------------
*
* var _sessionStorage = safeStorage.getStorage('session');
* _sessionStorage.setItem('myCat', 'foo');
* var cat = _sessionStorage.getItem('myCat');
* _sessionStorage.removeItem('myCat');
* _sessionStorage.clear();
*/

// The wrapper object
var safeStorage = {

    STORAGE_TYPES: ['local', 'session'],
    dummyStorage: null,

    // Validates if the requested storage is available
    Validate: function (storageType) {
        var stamp = (new Date()).getTime() + "",
            key = "_test_";
        try {
            if (!window.hasOwnProperty(storageType + "Storage")) {
                return false;
            }
            var s = window[storageType + "Storage"];
            // Robust, cross-browser storage detection
            s.setItem(key, stamp);
            if (s.getItem(key) === stamp) {
                s.removeItem(key);
                return !!s;
            }
        } catch (err) {
            return false;
        }
        return false;
    },

    // Returns the requested storage if available, else returns an instance of dummy storage
    getStorage: function (storageType) {
        var storageTypeIndex = this.STORAGE_TYPES.indexOf(storageType) || 0;
        for (var index = storageTypeIndex; index < this.STORAGE_TYPES.length; index++) {
            var isValid = this.Validate(this.STORAGE_TYPES[index]);
            if (isValid) {
                return window[storageType + "Storage"];
            }
        }

        if(!this.dummyStorage){
            this.dummyStorage = new this.DummyStorage();
        }

        return this.dummyStorage;
    },

    // Dummy storage object and methods
    DummyStorage: function () {
        var localStorage = {};
        return {
            getItem: function (key) {
                return localStorage[key] ? localStorage[key] : null;
            },
            setItem: function (key, value) {
                localStorage[key] = value;
            },
            removeItem: function (key) {
                delete localStorage[key];
            },
            clear: function () {
                localStorage = {};
            }
        };
    }
}

👍

Have a question?

Feel free to reach out on our new Community Discussion page!