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!
Updated over 2 years ago