Semi Anonymous

scalable, localStorage,

UX goodies

Scenarios


When it's ok, when it's not?
filter choices
recommendations

Can a site know you better than yourself?
hypothetical: DrupalCon

Entirely profiling driven.
hypothetical: Netflix
hypothetical: Coachella


Need

OMG, caching.
Drupal treats all anonymous users the same (mostly).
 The Drupal data storage go-to is mySQL
(SOLR, memcache)


Neat

Session-only data at any scale.
More rich "cookie-ish" storage.
Anonymous user profiling/personalization.
OMG, front-end.

<Links>


lawnchair.js (1798)
drupal/amplifyjs {bloat} (1198)

<my_LINKs!>

@Todo


  1. Data Layer separation (for GA)
  2. Views Integration!!!
  3. Stash/restore [#2279289]
  4. GUID? (supercookie)
  5. hasUserSeen(type, thing) [#2279301]

Let's Go!


Anyone stashing anything in localStorage today?

Integration ideas with Drupal?

Useful JS libraries and abstractions are available?

Basics


$.jStorage.set('myThing', 'the vale of your thing');$.jStorage.get('myThing');
allTheThings = $.jStorage.index();

Better with JSON
searchHabits = {
  'lastSearch': "funny cat videos",
  'resultsClicked': 8,
  'sort': 'popularity'
}

$.jStorage.set('MySearchPreferences', JSON.stringify(searchHabits));

prefs = JSON.parse($.jStorage.get('MySearchPreferences'));

User Storage


// All setup for you.
{
  "user.origin" : {
    "url" : "http://www.mysite.com/some-great-page?param=value",
    "timestamp" : "398649600",
    "referrer" : "http://www.anothersite.com/their-linking-page"
  },
  "user.session_origin" : {
    "url" : "http://www.mysite.com/recent-entry-point",
    "timestamp" : "398649999"
  }
}
// Just grab it.origin = JSON.parse($.jStorage.get('user.origin'));alert("You've been around " + (Date.now() - origin.timestamp) + " seconds.";

Meta data

{
  "nid" : "123",
  "title" : "My Cool Page",
  "entityType" : "node",
  "bundle" : "article",
  "uid" : "555",
  "language" : "en",
  "taxonomy" : {
    "special_category" : {
      "25" : "Term Name",
      "26" : "Another Term"
    },
    "my_type" : {
      "13" : "Some Tag",
    }
  }
}
if (typeof dataLayer.taxonomy.my_category !== 'undefined') {
  if (dataLayer.taxonomy.my_category.hasOwnProperty('25')) {
    doMyAction(dataLayer.uid, dataLayer.language, dataLayer.title);
  }
}

Tracking!


// Events look like this.
{
  "track.browsing.398649600" : {
    "url" : "http://www.mysite.com/some-great-page",
    "taxonomy" : {
      "my_category" : {
        "25" : "Term Name",
        "26" : "Another Term"
      },
      "my_types" : {
        "13" : "Some Tag"
      }
    }
  }
}
// Grab them.
$.each(semiAnon.getActivities('browsing'), function (key, record) {
  someComparison(record.url);
});

Anonymous Favorites!


omgFavs = semiAnon.getFavoriteTerms();
{
  "my_category" : {
    "123" : {
      "count" : 5,
      "name" : "My Term"
    },
    "456" : {
      "count" : 2,
      "name" : "My Other Term"
    },
  },
  "my_type" : {
    "555" : {
      "count" : 7,
      "name" : "My Type"
    }
  }
}

Using Favorites


if (favData.hasOwnProperty('my_vocab')) {
  // Could use low-dash.
  favVocabData = new Drupal.SemiAnon.Collection(favData['my_vocab']);

  if(favData['my_vocab'][favVocabData.keys()[0]].count >= myThreshold) {
    userValue = favData.property;
  }
}

That looks hard; oh Views integration!
Threshold is global.

Semi Anonymous: scalable localStorage UX

By Josh Lind

Semi Anonymous: scalable localStorage UX

Using the DB for anonymous UX improvements? There is a better way. Due to scaling the browser is fine place to stash data. LocalStorage can also enhance anonymous UX through profiling and non-permanent saving.

  • 918