Updated logger and demo
diff --git a/dashboard/files/test_app/css/map.css b/dashboard/files/test_app/css/map.css
index b5281fa..2d0022d 100644
--- a/dashboard/files/test_app/css/map.css
+++ b/dashboard/files/test_app/css/map.css
@@ -9,7 +9,7 @@
 .output {
     position: fixed;
     height: 80%;
-    width: 600px;
+    width: 700px;
     /* padding: 20px; */
     font-size: 10px;
     overflow: hidden;
diff --git a/dashboard/files/test_app/index.html b/dashboard/files/test_app/index.html
index 7f722c6..11122a3 100644
--- a/dashboard/files/test_app/index.html
+++ b/dashboard/files/test_app/index.html
@@ -28,28 +28,28 @@
         <h3 class="text-muted">User-ALE Examples</h3>
     </div>
 
-    <div class="col-md-6">
+    <div class="col-md-5">
         <div class="row buttons-grp">
             <h3 id="buttons" class="section-header">Buttons<a class="anchorjs-link" href="#buttons"><span
                     class="anchorjs-icon"></span></a></h3>
 
-            <form action="">
+            <!--<form action="">-->
                 <div class="form-group">
                     <a class="btn btn-default" href="#" role="button">Link</a>
                     <button class="btn btn-default" type="submit">Button</button>
                     <input class="btn btn-default" type="button" value="Input">
                     <input class="btn btn-default" type="submit" value="Submit">
                 </div>
-            </form>
+            <!--</form>-->
 
-            <form action="">
+            <!--<form action="">-->
                 <div class="form-group">
                     <label for="radio-button0">Male</label>
                     <input class="rdbtn" id="radio-button0" type="radio" name="sex" value="male">
                     <label for="radio-button1">Female</label>
                     <input class="rdbtn" id="radio-button1" type="radio" name="sex" value="female">
                 </div>
-            </form>
+            <!--</form>-->
         </div>
         <div class="row">
             <h3 id="menus" class="section-header">Menus<a class="anchorjs-link" href="#menus"><span
@@ -85,7 +85,7 @@
 
 
             <div class="grp">
-                <form>
+                <!--<form>-->
                     <div class="form-group">
                         <label for="query_name">Query Name</label>
                         <input id="textbox0" type="text" class="textbox form-control" id="query_name"
@@ -97,7 +97,7 @@
                                placeholder="Query Country">
                     </div>
                     <button type="submit" class="btn btn-default">Execute</button>
-                </form>
+                <!--</form>-->
             </div>
 
             <div class="grp">
@@ -119,12 +119,14 @@
             <div class="form-group">
                 <input id="map-button0" class="btn btn-default" type="button" value="Paris">
                 <input id="map-button1" class="btn btn-default" type="button" value="Chicago">
+                <input id="map-button2" class="btn btn-default" type="button" value="Add Marker">
+                <input id="map-button3" class="btn btn-default" type="button" value="Remove Marker">
             </div>
             <div id="map-container"></div>
         </div>
 
     </div>
-    <div class="col-md-6">
+    <div class="col-md-7">
         <div class="output">
             <table>
                 <thead>
@@ -133,6 +135,7 @@
                     <th width="110px">COMPONENT ID</th>
                     <th width="110px">COMPONENT TYPE</th>
                     <th width="110px">COMPONENT GROUP</th>
+                    <th width="100px">COMPONENT OBJECT</th>
                     <th width="60px">SOURCE</th>
                 </thead>
                 <tbody>
@@ -170,6 +173,6 @@
 
 <script src="js/map.js"></script>
 <script src="js/logging.js"></script>
-<script src="../../../helper-libs/javascript/userale.js"></script>
+<script src="js/userale.js"></script>
 </body>
 </html>
\ No newline at end of file
diff --git a/dashboard/files/test_app/js/logging.js b/dashboard/files/test_app/js/logging.js
index e82f702..08a28c3 100644
--- a/dashboard/files/test_app/js/logging.js
+++ b/dashboard/files/test_app/js/logging.js
@@ -3,20 +3,56 @@
  */
 $(document).ready(function () {
     //var ale2 = new userale();
-    var userale = new userale({
+    var slice = [].slice;
+
+    extend = function() {
+        var i, key, len, object, objects, out, value;
+        objects = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+        out = {};
+        for (i = 0, len = objects.length; i < len; i++) {
+            object = objects[i];
+            for (key in object) {
+                value = object[key];
+                out[key] = value;
+            }
+        }
+        return out;
+    };
+
+    var defaultMsg = {
+        activity: null,
+        action: null,
+        component: {
+            id: null,
+            type: null,
+            group: null
+        },
+        source: null,
+        object: null,
+        tags: [],
+        meta: {}
+    };
+
+    var ale2 = new userale(
+        {
         loggingUrl: '',
         toolName: 'dave',
         toolVersion: '2.3',
         componentGroups: [
             'map_group',
-            'input_group'
+            'input_group',
+            'top',
+            'dropdown_group',
+            'button_group',
+            'query_group'
         ],
-        workerUrl: '../../../helper-libs/javascript/draper.activity_worker-2.1.1.js',
+        workerUrl: 'js/userale-worker.js',
         debug: true,
         sendLogs: false
     });
 
-    userale.register()
+    window.ale2 = ale2;
+    ale2.register()
 
     var template = _.template(
         "<tr>" +
@@ -25,14 +61,16 @@
             "<td class='c'><%- component.id %></td>" +
             "<td class='d'><%- component.type %></td>" +
             "<td class='e'><%- component.group %></td>" +
+            "<td class='e'><%- object %></td>" +
             "<td class='f'><%- source %></td>" +
         "</tr>"
     );
     function log(msg) {
+        msg = extend(defaultMsg, msg);
         var elem = $(template(msg))
             .appendTo('.output tbody');
 
-        userale.log(msg);
+        ale2.log(msg);
 
         setTimeout(function () {
             elem.fadeOut(400, function () {
@@ -43,51 +81,53 @@
 
     }
 
+    window.myLog = log;
+
 
 
     $('.buttons-grp .btn')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'button_group'
                 },
                 source: 'user',
                 object: null,
-                tags: ['a', 'b']
+                tags: ['submit']
             };
             log(msg);
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'button_group'
                 },
                 source: 'user',
                 object: null,
-                tags: ['a', 'b']
+                tags: ['submit']
             };
             log(msg);
         })
         .click(function () {
             var msg = {
-                activity: ale.activities.PERFORM,
+                activity: 'perform',
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'button_group'
                 },
                 source: 'user',
                 object: null,
-                tags: ['a', 'b']
+                tags: ['submit']
             };
             log(msg);
         });
@@ -95,11 +135,11 @@
     $('.rdbtn')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.RADIOBUTTON,
+                    type: 'radiobutton',
                     group: 'button_group'
                 },
                 source: 'user',
@@ -110,11 +150,11 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.RADIOBUTTON,
+                    type: 'radiobutton',
                     group: 'button_group'
                 },
                 source: 'user',
@@ -129,7 +169,7 @@
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.RADIOBUTTON,
+                    type: 'radiobutton',
                     group: 'button_group'
                 },
                 source: 'user',
@@ -142,11 +182,11 @@
     $('.dd-list')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.DROPDOWNLIST,
+                    type: 'dropdownlist',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -157,11 +197,11 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.DROPDOWNLIST,
+                    type: 'dropdownlist',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -177,7 +217,7 @@
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.DROPDOWNLIST,
+                    type: 'dropdownlist',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -190,11 +230,11 @@
     $('.dd-item')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.LISTITEM,
+                    type: 'listitem',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -205,11 +245,11 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.LISTITEM,
+                    type: 'listitem',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -220,11 +260,11 @@
         })
         .click(function () {
             var msg = {
-                activity: ale.activities.PERFORM,
+                activity: 'perform',
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.LISTITEM,
+                    type: 'listitem',
                     group: 'dropdown_group'
                 },
                 source: 'user',
@@ -234,15 +274,15 @@
             log(msg);
         });
 
-    $('.textbox')
+    $('.query-group .textbox')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.TEXTBOX,
-                    group: 'input_group'
+                    type: 'textbox',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: null,
@@ -252,12 +292,12 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.TEXTBOX,
-                    group: 'input_group'
+                    type: 'textbox',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: null,
@@ -267,12 +307,12 @@
         })
         .click(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'FOCUS',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.TEXTBOX,
-                    group: 'input_group'
+                    type: 'textbox',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: null,
@@ -286,8 +326,8 @@
                 action: 'ENTERTEXT',
                 component: {
                     id: this.getAttribute('id'),
-                    type: ale.components.TEXTBOX,
-                    group: 'input_group'
+                    type: 'textbox',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: null,
@@ -299,11 +339,11 @@
     $('.map-group .btn')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -314,11 +354,11 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -329,11 +369,11 @@
         })
         .click(function () {
             var msg = {
-                activity: ale.activities.PERFORM,
+                activity: 'perform',
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -346,11 +386,11 @@
     $('.query-group .btn')
         .mouseover(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'query_group'
                 },
                 source: 'user',
@@ -361,11 +401,11 @@
         })
         .mouseout(function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'query_group'
                 },
                 source: 'user',
@@ -376,11 +416,11 @@
         })
         .click(function () {
             var msg = {
-                activity: ale.activities.PERFORM,
+                activity: 'perform',
                 action: 'CLICK',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.BUTTON,
+                    type: 'button',
                     group: 'query_group'
                 },
                 source: 'user',
@@ -394,11 +434,11 @@
     map
         .on('mouseover', function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOVER',
                 component: {
                     id: 'UNK',
-                    type: ale.components.MAP,
+                    type: 'map',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -409,11 +449,11 @@
         })
         .on('mouseout', function () {
             var msg = {
-                activity: ale.activities.INSPECT,
+                activity: 'inspect',
                 action: 'MOUSEOUT',
                 component: {
                     id: 'UNK',
-                    type: ale.components.MAP,
+                    type: 'map',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -424,11 +464,11 @@
         })
         .on('zoomstart', function () {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'ZOOM',
                 component: {
                     id: 'UNK',
-                    type: ale.components.MAP,
+                    type: 'map',
                     group: 'map_group'
                 },
                 source: 'unk',
@@ -439,11 +479,11 @@
         })
         .on('dragstart', function () {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'DRAG',
                 component: {
                     id: 'UNK',
-                    type: ale.components.MAP,
+                    type: 'map',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -454,11 +494,11 @@
         })
         .on('dragend', function () {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'DRAG',
                 component: {
                     id: 'UNK',
-                    type: ale.components.MAP,
+                    type: 'map',
                     group: 'map_group'
                 },
                 source: 'user',
@@ -469,7 +509,7 @@
         })
         .on('moveend', function () {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'MOVE',
                 component: {
                     id: 'UNK',
@@ -487,43 +527,68 @@
     $('.slider')
         .on("slidestart", function (event, ui) {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'SLIDE',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.SLIDER,
-                    group: 'input_group'
+                    type: 'slider',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: 'HANDLE',
                 tags: ['a', 'b']
             };
             log(msg);
+
+
+            var msg = {
+                activity: 'alter',
+                component: {
+                    type: 'slider',
+                    group: 'query_group'
+                },
+                source: 'system',
+                object: 'LABEL',
+                tags: []
+            };
+            log(msg);
         })
         .on("slidestop", function (event, ui) {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'SLIDE',
                 component: {
                     id: this.getAttribute('id') || 'UNK',
-                    type: ale.components.SLIDER,
-                    group: 'input_group'
+                    type: 'slider',
+                    group: 'query_group'
                 },
                 source: 'user',
                 object: 'HANDLE',
                 tags: ['a', 'b']
             };
             log(msg);
+
+            var msg = {
+                activity: 'alter',
+                component: {
+                    type: 'slider',
+                    group: 'query_group'
+                },
+                source: 'system',
+                object: 'LABEL',
+                tags: []
+            };
+            log(msg);
         });
 
     $(window)
         .on("scroll", function() {
             var msg = {
-                activity: ale.activities.ALTER,
+                activity: 'alter',
                 action: 'SCROLL',
                 component: {
                     id: 'UNK',
-                    type: ale.components.WINDOW,
+                    type: 'window',
                     group: 'top'
                 },
                 source: 'unk',
diff --git a/dashboard/files/test_app/js/map.js b/dashboard/files/test_app/js/map.js
index 230139b..d3ac9ac 100644
--- a/dashboard/files/test_app/js/map.js
+++ b/dashboard/files/test_app/js/map.js
@@ -12,6 +12,7 @@
 
     window.map = map;
 
+    var markers = [];
     $('#map-button0').click(function() {
         map.setView(L.latLng(48.8567, 2.3508), 10)
     });
@@ -20,6 +21,50 @@
         map.setView(L.latLng(41.8369, -87.6847), 11)
     });
 
+    $('#map-button2').click(function() {
+        var bounds = map.getBounds();
+
+        var west = bounds.getWest(),
+            north = bounds.getNorth(),
+            east = bounds.getEast(),
+            south = bounds.getSouth();
+
+        var lat = south + (north-south)*Math.random(),
+            lng = west + (east-west)*Math.random();
+
+        var marker = L.marker([lat, lng]).addTo(map);
+
+
+        markers.push(marker);
+        myLog({
+            activity: 'add',
+            component: {
+                type: 'map',
+                group: 'map_group'
+            },
+            source: 'system',
+            object: 'marker',
+            tags: []
+        })
+    });
+
+    $('#map-button3').click(function() {
+        var marker = markers.pop()
+
+        map.removeLayer(marker);
+
+        myLog({
+            activity: 'remove',
+            component: {
+                type: 'map',
+                group: 'map_group'
+            },
+            source: 'system',
+            object: 'marker',
+            tags: []
+        })
+    });
+
     $(function() {
         $( "#slider0" ).slider();
 
diff --git a/dashboard/files/test_app/js/userale.js b/dashboard/files/test_app/js/userale.js
new file mode 100644
index 0000000..a42c066
--- /dev/null
+++ b/dashboard/files/test_app/js/userale.js
@@ -0,0 +1,176 @@
+// Generated by CoffeeScript 1.9.1
+(function() {
+  var ACTIVITIES, ELEMENTS, default_msg, defaults, extend, getParameterByName, userale,
+    slice = [].slice,
+    indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
+
+  ACTIVITIES = ['ADD', 'REMOVE', 'CREATE', 'DELETE', 'SELECT', 'DESELECT', 'ENTER', 'LEAVE', 'INSPECT', 'ALTER', 'HIDE', 'SHOW', 'OPEN', 'CLOSE', 'PERFORM'];
+
+  ELEMENTS = ['BUTTON', 'CANVAS', 'CHECKBOX', 'COMBOBOX', 'DATAGRID', 'DIALOG_BOX', 'DROPDOWNLIST', 'FRAME', 'ICON', 'INFOBAR', 'LABEL', 'LINK', 'LISTBOX', 'LISTITEM', 'MAP', 'MENU', 'MODALWINDOW', 'PALETTEWINDOW', 'PANEL', 'PROGRESSBAR', 'RADIOBUTTON', 'SLIDER', 'SPINNER', 'STATUSBAR', 'TAB', 'TABLE', 'TAG', 'TEXTBOX', 'THROBBER', 'TOAST', 'TOOLBAR', 'TOOLTIP', 'TREEVIEW', 'WINDOW', 'WORKSPACE', 'OTHER'];
+
+  console.log('in userale');
+
+  extend = function() {
+    var i, key, len, object, objects, out, value;
+    objects = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    out = {};
+    for (i = 0, len = objects.length; i < len; i++) {
+      object = objects[i];
+      for (key in object) {
+        value = object[key];
+        out[key] = value;
+      }
+    }
+    return out;
+  };
+
+  getParameterByName = function(name) {
+    var regex, results;
+    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
+    regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
+    results = regex.exec(location.search);
+    return results = results ? decodeURIComponent(results[1].replace(/\+/g, " ")) : "";
+  };
+
+  defaults = {
+    loggingUrl: '',
+    toolName: 'UNK',
+    toolVersion: 'UNK',
+    workerUrl: 'userale-worker.js',
+    debug: true,
+    sendLogs: true,
+    componentGroups: []
+  };
+
+  default_msg = {
+    activity: null,
+    action: null,
+    component: {
+      id: null,
+      type: null,
+      group: null
+    },
+    source: null,
+    object: null,
+    tags: [],
+    meta: {}
+  };
+
+  userale = (function() {
+    function userale(options) {
+      this.options = extend(defaults, options);
+      if (this.options.componentGroups.constructor === !Array) {
+        this.options.componentGroups = [this.options.componentGroups];
+      }
+      this.options.version = '3.0.0';
+      this.worker = new Worker(this.options.workerUrl);
+      this.worker.postMessage({
+        cmd: 'setLoggingUrl',
+        msg: this.options.loggingUrl
+      });
+      this.debug(this.options.debug);
+      this.sendLogs(this.options.sendLogs);
+    }
+
+    userale.prototype.register = function() {
+      this.options.sessionID = getParameterByName('USID');
+      this.options.client = getParameterByName('client');
+      console.log(this.options.sessionID);
+      if (!this.options.sessionID) {
+        this.options.sessionID = this.options.toolName.slice(0, 3).toUpperCase() + new Date().getTime();
+        console.warn('USERALE: NO SESSION ID, MAKING ONE UP.  You can pass one in as url parameter (127.0.0.1?USID=12345)');
+      }
+      if (!this.options.client) {
+        this.options.client = 'UNK';
+        console.warn('USERALE: NO CLIENT, MAKING ONE UP.   You can pass one in as url parameter (127.0.0.1?client=roger)');
+      }
+      return this.worker.postMessage({
+        cmd: 'sendBuffer',
+        msg: ''
+      });
+    };
+
+    userale.prototype.log = function(msg) {
+      var activities, activity, elementType, i, key, len, ref, value, x;
+      for (key in msg) {
+        value = msg[key];
+        msg = extend(default_msg, msg);
+        if (key === 'component') {
+          if (ref = value.group, indexOf.call(this.options.componentGroups, ref) < 0) {
+            console.warn(value.group + " is NOT in component groups");
+          }
+          elementType = value.type.toUpperCase();
+          if (indexOf.call(ELEMENTS, elementType) < 0) {
+            console.warn("USERALE: Unrecognized element - " + elementType);
+          } else if ((elementType === 'OTHER') && (msg.meta.element == null)) {
+            console.warn("USERALE: Element type set to 'other', but 'element' not set in meta object ");
+          }
+          msg.component.type = elementType;
+        }
+        if (key === 'activity') {
+          activities = (function() {
+            var i, len, ref1, results1;
+            ref1 = value.split('_');
+            results1 = [];
+            for (i = 0, len = ref1.length; i < len; i++) {
+              x = ref1[i];
+              results1.push(x.toUpperCase());
+            }
+            return results1;
+          })();
+          for (i = 0, len = activities.length; i < len; i++) {
+            activity = activities[i];
+            if (indexOf.call(ACTIVITIES, activity) < 0) {
+              console.warn("USERALE: Unrecognized activity - " + activity);
+            }
+          }
+          msg[key] = activities;
+        }
+        if (key === 'source') {
+          value = value.toUpperCase();
+          if (value !== 'USER' && value !== 'SYSTEM' && value !== 'UNK') {
+            console.warn("USERALE: Unrecognized source - " + value);
+            msg[key] = null;
+          } else {
+            msg[key] = value.toUpperCase();
+          }
+        }
+      }
+      msg.timestamp = new Date().toJSON();
+      msg.client = this.options.client;
+      msg.toolName = this.options.toolName;
+      msg.toolVersion = this.options.toolVersion;
+      msg.sessionID = this.options.sessionID;
+      msg.language = 'JavaScript';
+      msg.useraleVersion = this.version;
+      return this.worker.postMessage({
+        cmd: 'sendMsg',
+        msg: msg
+      });
+    };
+
+    userale.prototype.debug = function(onOff) {
+      this.options.debug = onOff;
+      return this.worker.postMessage({
+        cmd: 'setEcho',
+        msg: onOff
+      });
+    };
+
+    userale.prototype.sendLogs = function(onOff) {
+      this.options.sendLogs = onOff;
+      return this.worker.postMessage({
+        cmd: 'setTesting',
+        msg: !onOff
+      });
+    };
+
+    return userale;
+
+  })();
+
+  window.userale = userale;
+
+}).call(this);
+
+//# sourceMappingURL=userale.js.map
diff --git a/dashboard/files/test_app/js/userale.js.map b/dashboard/files/test_app/js/userale.js.map
new file mode 100644
index 0000000..0c6ff65
--- /dev/null
+++ b/dashboard/files/test_app/js/userale.js.map
@@ -0,0 +1,10 @@
+{
+  "version": 3,
+  "file": "userale.js",
+  "sourceRoot": "",
+  "sources": [
+    "userale.coffee"
+  ],
+  "names": [],
+  "mappings": "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"
+}
\ No newline at end of file
diff --git a/helper-libs/javascript/draper.activity_worker-2.1.1.js b/helper-libs/javascript/draper.activity_worker-2.1.1.js
index 7ce3b8f..1b6c667 100644
--- a/helper-libs/javascript/draper.activity_worker-2.1.1.js
+++ b/helper-libs/javascript/draper.activity_worker-2.1.1.js
@@ -3,7 +3,7 @@
 var intervalTime = 5000; //send every 5 seconds
 var testing = false;
 var echo = true;
-var msg = 'DRAPER LOG: ';
+var msg = 'USERALE: ';
 
 // Register the interval timer to poll every intervalTime whether
 // is data that is needed to be send to the server or not.
@@ -91,9 +91,9 @@
             // server.
             case 'setTesting':
                 if (data.msg) 
-                    msg = 'DRAPER LOG: (TESTING) ';
+                    msg = 'USERALE: (TESTING) ';
                 else 
-                    msg = 'DRAPER LOG: ';
+                    msg = 'USERALE: ';
                 
                 testing = data.msg;
                 break;
diff --git a/helper-libs/javascript/userale.coffee b/helper-libs/javascript/userale.coffee
index cc463ec..9abac6b 100644
--- a/helper-libs/javascript/userale.coffee
+++ b/helper-libs/javascript/userale.coffee
@@ -1,34 +1,78 @@
-activities = [
-  'add',
-  'remove',
-  'create',
-  'delete',
-  'select',
-  'deselect',
-  'enter',
-  'leave',
-  'inspect',
-  'alter',
-  'hide',
-  'show'
+ACTIVITIES = [
+  'ADD',
+  'REMOVE',
+  'CREATE',
+  'DELETE',
+  'SELECT',
+  'DESELECT',
+  'ENTER',
+  'LEAVE',
+  'INSPECT',
+  'ALTER',
+  'HIDE',
+  'SHOW',
+  'OPEN',
+  'CLOSE'
+  'PERFORM'
 ]
 
+ELEMENTS = [
+  'BUTTON'
+  'CANVAS'
+  'CHECKBOX'
+  'COMBOBOX'
+  'DATAGRID'
+  'DIALOG_BOX'
+  'DROPDOWNLIST'
+  'FRAME'
+  'ICON'
+  'INFOBAR'
+  'LABEL'
+  'LINK'
+  'LISTBOX'
+  'LISTITEM'
+  'MAP'
+  'MENU'
+  'MODALWINDOW'
+  'PALETTEWINDOW'
+  'PANEL'
+  'PROGRESSBAR'
+  'RADIOBUTTON'
+  'SLIDER'
+  'SPINNER'
+  'STATUSBAR'
+  'TAB'
+  'TABLE'
+  'TAG'
+  'TEXTBOX'
+  'THROBBER'
+  'TOAST'
+  'TOOLBAR'
+  'TOOLTIP'
+  'TREEVIEW'
+  'WINDOW'
+  'WORKSPACE'
+# Other is used in conjunction with softwareMetadata in order
+# to provide a component in which is not currently listed within
+# the COMPONENT list.
+  'OTHER'
+]
 
 
 console.log('in userale')
 
 extend = (objects...) ->
+  out = {}
   for object in objects
     for key, value of object
-      objects[0][key] = value
-  return objects[0]
+      out[key] = value
+  return out
 
 getParameterByName = (name) ->
   name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]")
   regex = new RegExp("[\\?&]" + name + "=([^&#]*)")
 
   results = regex.exec(location.search)
-  console.log(results)
   results = if results then decodeURIComponent(results[1].replace(/\+/g, " ")) else ""
 
 defaults = {
@@ -41,45 +85,113 @@
   componentGroups: []
 }
 
+default_msg = {
+  activity: null,
+  action: null,
+  component: {
+    id: null,
+    type: null,
+    group: null
+  },
+  source: null,
+  object: null,
+  tags: []
+  meta: {}
+}
+
 class userale
   constructor: (options)->
-
     @options = extend(defaults, options)
 
-    if @options.component_groups.contructor is not Array
-      @options.component_groups = [@options.component_groups]
+    if @options.componentGroups.constructor is not Array
+      @options.componentGroups = [@options.componentGroups]
 
     @options.version = '3.0.0'
 
     @worker = new Worker(@options.workerUrl)
 
+    @worker.postMessage({
+      cmd: 'setLoggingUrl',
+      msg: @options.loggingUrl
+    });
+
+    @debug(@options.debug)
+    @sendLogs(@options.sendLogs)
+
   register: () ->
-#    @toolName = toolName
-#    @toolVersion = toolVersion
-#    @component_groups = component_groups
+    @options.sessionID = getParameterByName('USID')
+    @options.client = getParameterByName('client')
 
-    @sessionID = getParameterByName('USID')
-    @client = getParameterByName('client')
+    console.log(@options.sessionID)
 
-    console.log(@sessionID)
-
-    if !@sessionID
-      @sessionID = @toolName[0..2].toUpperCase() + new Date().getTime()
+    if !@options.sessionID
+      @options.sessionID = @options.toolName[0..2].toUpperCase() + new Date().getTime()
       console.warn('USERALE: NO SESSION ID, MAKING ONE UP.  You can pass one in as url parameter (127.0.0.1?USID=12345)')
 
-    if !@client
-      @client = 'UNK'
+    if !@options.client
+      @options.client = 'UNK'
       console.warn('USERALE: NO CLIENT, MAKING ONE UP.   You can pass one in as url parameter (127.0.0.1?client=roger)')
 
     @worker.postMessage({cmd: 'sendBuffer', msg: ''})
 
   log: (msg) ->
     for key, value of msg
+      msg = extend(default_msg, msg)
       if key is 'component'
-        if value.group in @options.component_groups
-          console.log("#{ value.group } is in component groups")
-        else
+        if value.group not in @options.componentGroups
           console.warn("#{ value.group } is NOT in component groups")
 
+        elementType = value.type.toUpperCase()
+        if elementType not in ELEMENTS
+          console.warn("USERALE: Unrecognized element - #{ elementType }")
+        else if (elementType is 'OTHER') and !msg.meta.element?
+          console.warn("USERALE: Element type set to 'other', but 'element' not set in meta object ")
+
+        msg.component.type = elementType
+
+      if key is 'activity'
+        activities = (x.toUpperCase() for x in value.split('_'))
+        for activity in activities
+          if activity not in ACTIVITIES
+            console.warn("USERALE: Unrecognized activity - #{ activity }")
+
+        msg[key] = activities
+
+      if key is 'source'
+        value = value.toUpperCase()
+        if value not in ['USER', 'SYSTEM', 'UNK']
+          console.warn("USERALE: Unrecognized source - #{ value }")
+          msg[key] = null
+        else
+          msg[key] = value.toUpperCase()
+
+    msg.timestamp = new Date().toJSON()
+    msg.client = @options.client
+    msg.toolName = @options.toolName
+    msg.toolVersion = @options.toolVersion
+    msg.sessionID = @options.sessionID
+    msg.language = 'JavaScript'
+    msg.useraleVersion = @version
+
+    @.worker.postMessage({
+      cmd: 'sendMsg',
+      msg: msg
+    })
+
+  debug: (onOff) ->
+    @options.debug = onOff
+    @worker.postMessage({
+      cmd: 'setEcho',
+      msg: onOff
+    });
+
+  sendLogs: (onOff) ->
+    @options.sendLogs = onOff
+    @worker.postMessage({
+      cmd: 'setTesting',
+      msg: !onOff
+    });
+#    console.log(msg)
+
 
 window.userale = userale
\ No newline at end of file
diff --git a/helper-libs/javascript/userale.js b/helper-libs/javascript/userale.js
index 8d854f9..a42c066 100644
--- a/helper-libs/javascript/userale.js
+++ b/helper-libs/javascript/userale.js
@@ -1,24 +1,27 @@
 // Generated by CoffeeScript 1.9.1
 (function() {
-  var activities, defaults, extend, getParameterByName, userale,
+  var ACTIVITIES, ELEMENTS, default_msg, defaults, extend, getParameterByName, userale,
     slice = [].slice,
     indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
 
-  activities = ['add', 'remove', 'create', 'delete', 'select', 'deselect', 'enter', 'leave', 'inspect', 'alter', 'hide', 'show'];
+  ACTIVITIES = ['ADD', 'REMOVE', 'CREATE', 'DELETE', 'SELECT', 'DESELECT', 'ENTER', 'LEAVE', 'INSPECT', 'ALTER', 'HIDE', 'SHOW', 'OPEN', 'CLOSE', 'PERFORM'];
+
+  ELEMENTS = ['BUTTON', 'CANVAS', 'CHECKBOX', 'COMBOBOX', 'DATAGRID', 'DIALOG_BOX', 'DROPDOWNLIST', 'FRAME', 'ICON', 'INFOBAR', 'LABEL', 'LINK', 'LISTBOX', 'LISTITEM', 'MAP', 'MENU', 'MODALWINDOW', 'PALETTEWINDOW', 'PANEL', 'PROGRESSBAR', 'RADIOBUTTON', 'SLIDER', 'SPINNER', 'STATUSBAR', 'TAB', 'TABLE', 'TAG', 'TEXTBOX', 'THROBBER', 'TOAST', 'TOOLBAR', 'TOOLTIP', 'TREEVIEW', 'WINDOW', 'WORKSPACE', 'OTHER'];
 
   console.log('in userale');
 
   extend = function() {
-    var i, key, len, object, objects, value;
+    var i, key, len, object, objects, out, value;
     objects = 1 <= arguments.length ? slice.call(arguments, 0) : [];
+    out = {};
     for (i = 0, len = objects.length; i < len; i++) {
       object = objects[i];
       for (key in object) {
         value = object[key];
-        objects[0][key] = value;
+        out[key] = value;
       }
     }
-    return objects[0];
+    return out;
   };
 
   getParameterByName = function(name) {
@@ -26,7 +29,6 @@
     name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
     regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
     results = regex.exec(location.search);
-    console.log(results);
     return results = results ? decodeURIComponent(results[1].replace(/\+/g, " ")) : "";
   };
 
@@ -40,26 +42,46 @@
     componentGroups: []
   };
 
+  default_msg = {
+    activity: null,
+    action: null,
+    component: {
+      id: null,
+      type: null,
+      group: null
+    },
+    source: null,
+    object: null,
+    tags: [],
+    meta: {}
+  };
+
   userale = (function() {
     function userale(options) {
       this.options = extend(defaults, options);
-      if (this.options.component_groups.contructor === !Array) {
-        this.options.component_groups = [this.options.component_groups];
+      if (this.options.componentGroups.constructor === !Array) {
+        this.options.componentGroups = [this.options.componentGroups];
       }
       this.options.version = '3.0.0';
       this.worker = new Worker(this.options.workerUrl);
+      this.worker.postMessage({
+        cmd: 'setLoggingUrl',
+        msg: this.options.loggingUrl
+      });
+      this.debug(this.options.debug);
+      this.sendLogs(this.options.sendLogs);
     }
 
     userale.prototype.register = function() {
-      this.sessionID = getParameterByName('USID');
-      this.client = getParameterByName('client');
-      console.log(this.sessionID);
-      if (!this.sessionID) {
-        this.sessionID = this.toolName.slice(0, 3).toUpperCase() + new Date().getTime();
+      this.options.sessionID = getParameterByName('USID');
+      this.options.client = getParameterByName('client');
+      console.log(this.options.sessionID);
+      if (!this.options.sessionID) {
+        this.options.sessionID = this.options.toolName.slice(0, 3).toUpperCase() + new Date().getTime();
         console.warn('USERALE: NO SESSION ID, MAKING ONE UP.  You can pass one in as url parameter (127.0.0.1?USID=12345)');
       }
-      if (!this.client) {
-        this.client = 'UNK';
+      if (!this.options.client) {
+        this.options.client = 'UNK';
         console.warn('USERALE: NO CLIENT, MAKING ONE UP.   You can pass one in as url parameter (127.0.0.1?client=roger)');
       }
       return this.worker.postMessage({
@@ -69,21 +91,78 @@
     };
 
     userale.prototype.log = function(msg) {
-      var key, ref, results1, value;
-      results1 = [];
+      var activities, activity, elementType, i, key, len, ref, value, x;
       for (key in msg) {
         value = msg[key];
+        msg = extend(default_msg, msg);
         if (key === 'component') {
-          if (ref = value.group, indexOf.call(this.options.component_groups, ref) >= 0) {
-            results1.push(console.log(value.group + " is in component groups"));
-          } else {
-            results1.push(console.warn(value.group + " is NOT in component groups"));
+          if (ref = value.group, indexOf.call(this.options.componentGroups, ref) < 0) {
+            console.warn(value.group + " is NOT in component groups");
           }
-        } else {
-          results1.push(void 0);
+          elementType = value.type.toUpperCase();
+          if (indexOf.call(ELEMENTS, elementType) < 0) {
+            console.warn("USERALE: Unrecognized element - " + elementType);
+          } else if ((elementType === 'OTHER') && (msg.meta.element == null)) {
+            console.warn("USERALE: Element type set to 'other', but 'element' not set in meta object ");
+          }
+          msg.component.type = elementType;
+        }
+        if (key === 'activity') {
+          activities = (function() {
+            var i, len, ref1, results1;
+            ref1 = value.split('_');
+            results1 = [];
+            for (i = 0, len = ref1.length; i < len; i++) {
+              x = ref1[i];
+              results1.push(x.toUpperCase());
+            }
+            return results1;
+          })();
+          for (i = 0, len = activities.length; i < len; i++) {
+            activity = activities[i];
+            if (indexOf.call(ACTIVITIES, activity) < 0) {
+              console.warn("USERALE: Unrecognized activity - " + activity);
+            }
+          }
+          msg[key] = activities;
+        }
+        if (key === 'source') {
+          value = value.toUpperCase();
+          if (value !== 'USER' && value !== 'SYSTEM' && value !== 'UNK') {
+            console.warn("USERALE: Unrecognized source - " + value);
+            msg[key] = null;
+          } else {
+            msg[key] = value.toUpperCase();
+          }
         }
       }
-      return results1;
+      msg.timestamp = new Date().toJSON();
+      msg.client = this.options.client;
+      msg.toolName = this.options.toolName;
+      msg.toolVersion = this.options.toolVersion;
+      msg.sessionID = this.options.sessionID;
+      msg.language = 'JavaScript';
+      msg.useraleVersion = this.version;
+      return this.worker.postMessage({
+        cmd: 'sendMsg',
+        msg: msg
+      });
+    };
+
+    userale.prototype.debug = function(onOff) {
+      this.options.debug = onOff;
+      return this.worker.postMessage({
+        cmd: 'setEcho',
+        msg: onOff
+      });
+    };
+
+    userale.prototype.sendLogs = function(onOff) {
+      this.options.sendLogs = onOff;
+      return this.worker.postMessage({
+        cmd: 'setTesting',
+        msg: !onOff
+      });
     };
 
     return userale;
diff --git a/helper-libs/javascript/userale.js.map b/helper-libs/javascript/userale.js.map
index c393f51..0c6ff65 100644
--- a/helper-libs/javascript/userale.js.map
+++ b/helper-libs/javascript/userale.js.map
@@ -6,5 +6,5 @@
     "userale.coffee"
   ],
   "names": [],
-  "mappings": "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"
+  "mappings": "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"
 }
\ No newline at end of file