From 4582e7cd991f4da53771ce552928bc9b49600b91 Mon Sep 17 00:00:00 2001 From: Michael Keirnan Date: Tue, 11 Jun 2019 07:05:27 -0400 Subject: [PATCH 1/4] Add custom click properties --- README.md | 14 ++++++++++++++ src/index.js | 22 ++++++++++++++++++++++ test/ahoy_test.js | 30 ++++++++++++++++++++++++++++-- test/template.html | 4 ++++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0acbbae3..38dfe513 100644 --- a/README.md +++ b/README.md @@ -131,6 +131,20 @@ Properties - text - `View Account` - href - `/account` +Setting custom properties with `data-ahoy-click-` attributes: + +```html +Extra +``` + +Properties + +- tag - `a` +- id - `account-link` +- text - `Extra` +- href - `/my_product` +- properties - `{product_id: '123', cat: '456'}` + ### Submits ```javascript diff --git a/src/index.js b/src/index.js index 59bca9c2..a806e9c5 100644 --- a/src/index.js +++ b/src/index.js @@ -333,6 +333,23 @@ function createVisit() { } } +function extraClickProperties(element) { + let prefix = "data-ahoy-click-"; + + let properties = {}; + + let attributeNames = element.getAttributeNames(); + for (let i = 0; i < attributeNames.length; i++) { + let attributeName = attributeNames[i]; + if (attributeName.startsWith(prefix)) { + let propertyName = attributeName.substring(prefix.length); + properties[propertyName] = element.getAttribute(attributeName); + } + } + + return properties; +} + ahoy.getVisitId = ahoy.getVisitToken = function () { return getCookie("ahoy_visit"); }; @@ -419,6 +436,11 @@ ahoy.trackClicks = function () { let properties = eventProperties(e); properties.text = properties.tag == "input" ? target.value : (target.textContent || target.innerText || target.innerHTML).replace(/[\s\r\n]+/g, " ").trim(); properties.href = target.href; + + let extraProperties = extraClickProperties(target); + if (Object.keys(extraProperties).length > 0) { + properties.properties = extraProperties; + } ahoy.track("$click", properties); }); }; diff --git a/test/ahoy_test.js b/test/ahoy_test.js index f5b2d034..1bcd0343 100644 --- a/test/ahoy_test.js +++ b/test/ahoy_test.js @@ -84,12 +84,12 @@ test('View tracking', (t) => { }); test('Click tracking', (t) => { - t.plan(6); + t.plan(7); fauxJax.install(); fauxJax.once('request', function(request) { const event = JSON.parse(request.requestBody).events[0]; - const properties = event.properties + const properties = event.properties; t.equal(request.requestMethod, 'POST', 'Should use POST method'); t.equal(request.requestURL, '/ahoy/events', 'Should POST to correct URL'); @@ -97,6 +97,7 @@ test('Click tracking', (t) => { t.equal(properties.id, 'ahoy-test-link', 'Should set event id property'); t.equal(properties.section, 'Header', 'Should set event section property'); t.equal(properties.text, 'Home', 'Should set event text property'); + t.equal(properties.properties, undefined, 'Should not set extra properties'); request.respond(200, {}, '{}'); fauxJax.restore(); @@ -105,3 +106,28 @@ test('Click tracking', (t) => { ahoy.trackClicks(); document.getElementById('ahoy-test-link').click(); }); + +test('Click tracking extra properties', (t) => { + t.plan(8); + + fauxJax.install(); + fauxJax.once('request', function(request) { + const event = JSON.parse(request.requestBody).events[0]; + const properties = event.properties; + + t.equal(request.requestMethod, 'POST', 'Should use POST method'); + t.equal(request.requestURL, '/ahoy/events', 'Should POST to correct URL'); + t.equal(event.name, '$click', 'Should set event name property'); + t.equal(properties.id, 'ahoy-test-link-extra', 'Should set event id property'); + t.equal(properties.section, 'Header', 'Should set event section property'); + t.equal(properties.text, 'Extra', 'Should set event text property'); + t.equal(properties.properties.foo, 'bar', 'Should set extra property "foo"'); + t.equal(properties.properties.the_answer, '42', 'Should set extra property "the_answer"'); + + request.respond(200, {}, '{}'); + fauxJax.restore(); + }); + + ahoy.trackClicks(); + document.getElementById('ahoy-test-link-extra').click(); +}); diff --git a/test/template.html b/test/template.html index 76875128..f87d2c4b 100644 --- a/test/template.html +++ b/test/template.html @@ -3,4 +3,8 @@
Home + Extra
From 741553bfdb8bcc36fd92aa12ef080782ffb3d6c4 Mon Sep 17 00:00:00 2001 From: Michael Keirnan Date: Wed, 8 Jan 2020 13:16:52 -0500 Subject: [PATCH 2/4] Update dash/underscore treatment - DOM data attributes generally use dashes instead of underscores and rails ERB templates replace undescores with dashes - update example in README to reflect this convention - convert dashes to underscores in generated event properties JSON to be consistent with consistent with Ahoy JSON naming convention --- README.md | 2 +- src/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38dfe513..35db15ef 100644 --- a/README.md +++ b/README.md @@ -134,7 +134,7 @@ Properties Setting custom properties with `data-ahoy-click-` attributes: ```html -Extra +Extra ``` Properties diff --git a/src/index.js b/src/index.js index a806e9c5..1e11afbc 100644 --- a/src/index.js +++ b/src/index.js @@ -342,7 +342,7 @@ function extraClickProperties(element) { for (let i = 0; i < attributeNames.length; i++) { let attributeName = attributeNames[i]; if (attributeName.startsWith(prefix)) { - let propertyName = attributeName.substring(prefix.length); + let propertyName = attributeName.substring(prefix.length).replace("-", "_"); properties[propertyName] = element.getAttribute(attributeName); } } From 1187b5255741f5c089074636937a23c1e88177f0 Mon Sep 17 00:00:00 2001 From: Michael Keirnan Date: Thu, 9 Jan 2020 09:07:10 -0500 Subject: [PATCH 3/4] Support JSON extra click properties --- README.md | 20 ++++++++++++++++++-- src/index.js | 5 +++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 35db15ef..c400290d 100644 --- a/README.md +++ b/README.md @@ -140,10 +140,26 @@ Setting custom properties with `data-ahoy-click-` attributes: Properties - tag - `a` -- id - `account-link` - text - `Extra` - href - `/my_product` -- properties - `{product_id: '123', cat: '456'}` +- properties - `{product_id: "123", cat: "456"}` + +Setting custom properties from JSON with `data-ahoy-click-json` attribute: + +```html +Extra JSON +``` + +JSON + +Properties + +- tag - `a` +- text - `JSON` +- href - `/link1` +- properties - `{some_flag: true, some_count: 42}` + +JSON allows typing and nesting extra properties, but requires HTML escaping. HTML escaping is automatic in many templating systems like ERB. ### Submits diff --git a/src/index.js b/src/index.js index 1e11afbc..4f7140e0 100644 --- a/src/index.js +++ b/src/index.js @@ -335,6 +335,11 @@ function createVisit() { function extraClickProperties(element) { let prefix = "data-ahoy-click-"; + let jsonAttribute = prefix + 'json'; + + if (element.hasAttribute(jsonAttribute)) { + return JSON.parse(element.getAttribute(jsonAttribute)); + } let properties = {}; From c5eec7ea74ecfffb7dd2e8f9636f159b0b61814b Mon Sep 17 00:00:00 2001 From: Michael Keirnan Date: Fri, 14 Feb 2020 09:40:37 -0500 Subject: [PATCH 4/4] Fix bug where extrProperties were nested (properties.properties) --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 4f7140e0..e8ea6677 100644 --- a/src/index.js +++ b/src/index.js @@ -443,8 +443,8 @@ ahoy.trackClicks = function () { properties.href = target.href; let extraProperties = extraClickProperties(target); - if (Object.keys(extraProperties).length > 0) { - properties.properties = extraProperties; + for (var propName in extraProperties) { + properties[propName] = extraProperties[propName]; } ahoy.track("$click", properties); });