diff --git a/DOCS.md b/DOCS.md
index 0228d39..3931b3f 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -119,7 +119,8 @@ groucho.config = {
]
}
```
-To write your own features, grab browsing history and work with it like this...
+
+To write your own features, grab browsing history and work with it. You'll need to use a little structure to define the condition, in this case: the name of the tracking group...
```javascript
$.each(groucho.getActivities('browsing'), function (key, record) {
@@ -270,45 +271,65 @@ var favCategoryTerms = groucho.getFavoriteTerms('*', false, 7);
You can register your own tracking activities like this...
```javascript
-// Track your own activities.
-$('.my-special-links').bind('click', function (e) {
- myObj.linkText = $(this).text()
- myObj.myProperty = $(this).attr('data-property');
- groucho.createActivity('my_activity', myObj);
+$('.videos a.play').bind('click', function() {
+ groucho.createActivity('watch', {
+ 'videoId' : $(this).data('videoId'),
+ 'category' : $(this).data('category'),
+ 'videoTitle' : $(this).text()
+ });
});
```
-They will be stored as key/value in jStorage. But can be returned as an array, filtered down to the group specified.
+They will be stored as key/value in jStorage. But can be returned as an array, filtered down to the group specified. Remember to structure the condition.
```javascript
-var myActivities = groucho.getActivities('my_activity');
+var myActivities = groucho.getActivities('watch');
```
+
```json
[{
- "_key" : "track.my_activity.398649600",
- "linkText" : "Link text from page",
- "myProperty" : "the-property-value"
+ "_key" : "track.watch.398649600",
+ "videoId" : 456,
+ "category" : "tutorial",
+ "videoTitle" : "Learn About Something"
}, {
- "_key" : "track.my_activity.398649999",
- "linkText" : "Other link text",
- "myProperty" : "this-property-value"
+ "_key" : "track.watch.398649999",
+ "videoId" : 789,
+ "category" : "fun",
+ "videoTitle" : "Be Entertained"
}]
```
-You can work directly with tracking activites and create your own smart functions...
+You can work directly with tracking activites and create your own smart functions. This example finds tutorial videos watched in the last week...
+
```javascript
-function myActivitySmarts () {
- var myActivities = groucho.getActivities('my_activity'),
- record;
-
- for (i in myActivities) {
- record = myActivities[i];
- if (myComparison(record.property, record.url, record._key.split('.')[2])) {
- count++;
+function recentVideos(timeframe, category) {
+ var conditions = [{'type' : [category]}],
+ activityList = groucho.getActivities('watch', conditions),
+ now = new Date().getTime(),
+ recentList = [],
+ timestamp;
+
+ for (var i in activityList) {
+ timestamp = activityList[i]._key.split('.')[2]);
+ if (timestamp > (now - timeframe)) {
+ recentList.push({
+ 'videoTitle' : activityList[i].videoTitle,
+ 'url' : activityList[i].url
+ });
}
}
- return count;
+
+ return recentList;
}
+
+$.each(recentVideos(604800, 'tutorial'), function() {
+ newItem = '
' + this.videoTitle + '';
+ $('ul.recentlyWatched').append(newItem);
+});
```
+_...but you shouldn't insert HTML this way._
+
+
### Local Storage
This library uses in-browser key/value localStorage with the convenient jStorage abstraction library. If you're new to localStorage, it's no big deal and is a new tool we should all be using.
diff --git a/README.md b/README.md
index e726074..c58df65 100644
--- a/README.md
+++ b/README.md
@@ -100,11 +100,11 @@ if (groucho.favoriteTerms.hasOwnProperty(taxonomy)) {
### Pageview Tracking
Use page view activity tracking to dig through history and alter UX.
-
```javascript
var history = groucho.getActivities('browsing'),
links = $('a.promoted'),
count = 0;
+
for (var i in history) {
// Determine if they've seen a page with a specific property.
if (history[i].hasOwnProperty('myProperty') count++;
@@ -114,37 +114,32 @@ if (count < 2) links.addClass('featured');
else if (count >= 2 && count < 7) links.addClass('reduced');
else links.addClass('hidden');
```
-Show the last viewed item of a given type. Example is last watched video...
-
-```javascript
-var history = groucho.getActivities('watch');
-if (history.length) {
- $.get("videos.json?id=" + history[0].videoId, function(data) {
- $('.recent').html(displayVideo(data));
- });
-}
-```
## Custom Activies
Register your own tracking activities like this...
+```javascript
+$('.videos a.play').bind('click', function() {
+ groucho.createActivity('watch', {'videoId' : 789});
+});
+```
+Retrieve activities later to personalize pages. Example swaps in the last watched video...
```javascript
-// Track your own activities.
-$('.my-special-links').bind('click', function (e) {
- groucho.createActivity('my_activity', {
- 'linkText' : $(this).text(),
- 'myProperty' : $(this).attr('data-property')
+var history = groucho.getActivities('watch');
+
+if (history.length) {
+ $.get("videos.json?id=" + history[0].videoId, function(data) {
+ $('.recent').find('.title').text(data.title)
+ .find('.graphic').text(data.graphic)
+ .find('a').attr('href', data.url);
});
-});
-// Later...
-myActivites = groucho.getActivities('my_activity');
+}
```
### Basic User Info
Wait for data availability and user basic user info.
-
```javascript
(function ($) {
$(document).ready(function(){
diff --git a/groucho.json b/groucho.json
index 02bd53b..f93f572 100644
--- a/groucho.json
+++ b/groucho.json
@@ -2,7 +2,7 @@
"name": "groucho",
"title": "Groucho",
"description": "Know more about your anonymous users. In-browser storage tracking tool.",
- "version": "0.2.1",
+ "version": "0.3.0",
"homepage": "https://github.com/tableau-mkt/groucho",
"author": {
"name": "Josh Lind",
diff --git a/src/groucho.js b/src/groucho.js
index da90ea9..bd15afd 100644
--- a/src/groucho.js
+++ b/src/groucho.js
@@ -117,35 +117,106 @@ var groucho = window.groucho || {};
* Access records of a specific tracking group.
*
* @param {string} group
- * Name of the tracking group to return values for.
+ * Strucutured conditions for activity lookup: {type, [conditionList]}.
+ * @param {array} conditions
+ * List of acceptable property [key/[values]] objects.
*
* return {array}
* List of tracking localStorage entries.
*/
- groucho.getActivities = function getActivities(group) {
+ groucho.getActivities = function getActivities(type, conditionList) {
- var results = $.jStorage.index(),
+ // Optional params.
+ var group = type || false,
+ conditions = conditionList || false,
+ groupMatch = new RegExp("^track." + group + ".", "g"),
+ results = $.jStorage.index(),
returnVals = [],
- matchable = new RegExp("^track." + group + ".", "g"),
record;
+ /**
+ * Confirm properties are of desired values.
+ * NOTE: String comparisons only!
+ *
+ * @param {array} conditions
+ * List of acceptable property [key/[values]] objects.
+ * @param {string} record
+ * History record to check against.
+ *
+ * @return {boolean}
+ * Result of match check.
+ */
+ function checkProperties(conditions, record) {
+ // Check all conditions, be picky about type.
+ if (conditions && conditions instanceof Array) {
+ for (var i in conditions) {
+ // Confirm an acceptable value.
+ if (checkValues(i, conditions[i], record)) {
+ addRecord(record);
+ }
+
+ }
+ }
+ else {
+ // No conditions, or wrong type-- add everything.
+ addRecord(record);
+ }
+ }
+
+ /**
+ * Confirm one of values matches the record.
+ * NOTE: String comparisons only!
+ *
+ * @param {string} property
+ * Property to check.
+ * @param {array} values
+ * List of acceptable values.
+ * @param {string} record
+ * History record to check against.
+ *
+ * @return {boolean}
+ * Result of match check.
+ */
+ function checkValues(property, values, record) {
+ // Check all values, be picky about type.
+ if (values instanceof Array) {
+ for (var i in values) {
+ // Confirm an acceptable value.
+ if (record.hasOwnProperty(property) && record.property === values[i]) {
+ addRecord(record);
+ // Only need one match per value set.
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Grab record from storage, add to returns.
+ *
+ * @param string key
+ * Browser storage lookup key.
+ */
+ function addRecord(key) {
+ record = $.jStorage.get(key);
+ // Move key to special property.
+ record._key = key;
+ returnVals.push(record);
+ }
+
+
+ // Look through storage index.
for (var i in results) {
// Remove unwanted types and return records.
if (group) {
- if (results[i].match(matchable) !== null) {
- // Collect relevant.
- record = $.jStorage.get(results[i]);
- // Move key to property.
- record._key = results[i];
- returnVals.push(record);
+ if (results[i].match(groupMatch) !== null) {
+ // Move on to checking conditions (potentially just add it).
+ checkProperties(conditions, results[i]);
}
}
else {
- // Collect and return all.
- record = $.jStorage.get(results[i]);
- // Move key to property.
- record._key = results[i];
- returnVals.push(record);
+ // Just check property or just add.
+ checkProperties(conditions, results[i]);
}
}
diff --git a/test/groucho_test.js b/test/groucho_test.js
index b008719..3f2782f 100644
--- a/test/groucho_test.js
+++ b/test/groucho_test.js
@@ -127,7 +127,7 @@
timeout = i * 150;
stop();
setTimeout(function () {
- groucho.createActivity('fake_thing', fakeData);
+ groucho.createActivity('fake_thing', fakeData);
start();
}, timeout);
}
@@ -158,6 +158,119 @@
});
+ //@todo Confirm granular activity request work.
+ test('Activity retrieval', 0, function() {
+
+ // Mock functions.
+ var counters = {
+ 'checkProperties': 0,
+ 'checkValues': 0,
+ 'addRecord': 0
+ };
+ groucho.getActivities.checkProperties = function() {
+ counters[this.name]++
+ };
+ groucho.getActivities.checkValues = function() {
+ counters[this.name]++
+ };
+ groucho.getActivities.addRecord = function() {
+ counters[this.name]++
+ };
+
+ // Create activities!
+ groucho.createActivity('testThingy', {
+ 'neato' : 'definately',
+ 'yep' : 'probably'
+ });
+ groucho.createActivity('testStuff', {
+ 'neato' : 'definately',
+ 'yep' : 'probably'
+ });
+ groucho.createActivity('testThingy', {
+ 'neato' : 'unclear'
+ });
+ groucho.createActivity('testThingy', {
+ 'wow' : 'indeed',
+ 'yep' : 'probably'
+ });
+
+ // Tests...
+ groucho.getActivities('testThingy');
+
+ groucho.getActivities('testStuff');
+
+ groucho.getActivities('testThingy', [
+ {'neato' : ['definately']}
+ ]);
+
+ groucho.getActivities('testThingy', [
+ {'neato' : ['definately', 'unclear']}
+ ]);
+
+ groucho.getActivities('testThingy', [
+ {'neato' : ['definately']},
+ {'wow' : ['indeed']}
+ ]);
+
+ groucho.createActivity('testStuff', [
+ {'neato' : ['unclear']},
+ {'neato' : ['definately']}
+ ]);
+
+
+
+
+/*
+
+ groucho.getActivities();
+
+ groucho.getActivities('fake_thing');
+
+ groucho.getActivities('wrong');
+
+ groucho.getActivities(
+ 'fake_thing',
+ [{'entityBundle'}]
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ [{'entityBundle' : 'article'}]
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ [{entityBundle' : ['article']}]
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ [{'entityBundle' : ['wrong', 'article']}}
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ ['entityBundle' : ['wrong']}]
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ [
+ {entityBundle' : ['article']},
+ {entityBundle' : ['article']}
+ ]
+ });
+
+ groucho.getActivities({
+ 'fake_thing',
+ [
+ {entityBundle' : ['article']},
+ {entityBundle' : ['profile', 'blog']}
+ ]
+ });
+*/
+
+ });
module('Favorites');