analytics-js-rails 0.11.0.rc1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +10 -0
- data/README.md +16 -9
- data/analytics-js-rails.gemspec +3 -2
- data/app/assets/javascripts/analytics.js +1978 -187
- data/app/views/analytics-js/_loader.html.erb +1 -2
- data/lib/analytics-js-rails.rb +9 -1
- data/lib/analytics-js/engine.rb +3 -0
- data/lib/analytics-js/version.rb +1 -1
- data/spec/lib/analytics-js-rails_spec.rb +25 -0
- data/spec/rails-app-3.2.14/.gitignore +15 -0
- data/spec/rails-app-3.2.14/.rspec +1 -0
- data/spec/rails-app-3.2.14/Gemfile +23 -0
- data/spec/rails-app-3.2.14/README.rdoc +261 -0
- data/spec/rails-app-3.2.14/Rakefile +7 -0
- data/spec/rails-app-3.2.14/app/assets/images/rails.png +0 -0
- data/spec/rails-app-3.2.14/app/assets/javascripts/application.js +15 -0
- data/spec/rails-app-3.2.14/app/assets/javascripts/static.js +2 -0
- data/spec/rails-app-3.2.14/app/assets/stylesheets/application.css +13 -0
- data/spec/rails-app-3.2.14/app/assets/stylesheets/static.css +4 -0
- data/spec/rails-app-3.2.14/app/controllers/application_controller.rb +3 -0
- data/spec/rails-app-3.2.14/app/controllers/static_controller.rb +4 -0
- data/spec/rails-app-3.2.14/app/helpers/application_helper.rb +2 -0
- data/spec/rails-app-3.2.14/app/helpers/static_helper.rb +2 -0
- data/spec/rails-app-3.2.14/app/mailers/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/app/models/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/app/views/layouts/application.html.erb +17 -0
- data/spec/rails-app-3.2.14/app/views/static/home.html.erb +2 -0
- data/spec/rails-app-3.2.14/config.ru +4 -0
- data/spec/rails-app-3.2.14/config/application.rb +66 -0
- data/spec/rails-app-3.2.14/config/boot.rb +6 -0
- data/spec/rails-app-3.2.14/config/database.yml +25 -0
- data/spec/rails-app-3.2.14/config/environment.rb +5 -0
- data/spec/rails-app-3.2.14/config/environments/development.rb +37 -0
- data/spec/rails-app-3.2.14/config/environments/production.rb +67 -0
- data/spec/rails-app-3.2.14/config/environments/test.rb +37 -0
- data/spec/rails-app-3.2.14/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/rails-app-3.2.14/config/initializers/inflections.rb +15 -0
- data/spec/rails-app-3.2.14/config/initializers/mime_types.rb +5 -0
- data/spec/rails-app-3.2.14/config/initializers/secret_token.rb +7 -0
- data/spec/rails-app-3.2.14/config/initializers/session_store.rb +8 -0
- data/spec/rails-app-3.2.14/config/initializers/wrap_parameters.rb +14 -0
- data/spec/rails-app-3.2.14/config/locales/en.yml +5 -0
- data/spec/rails-app-3.2.14/config/routes.rb +12 -0
- data/spec/rails-app-3.2.14/db/seeds.rb +7 -0
- data/spec/rails-app-3.2.14/lib/assets/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/lib/tasks/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/log/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/public/404.html +26 -0
- data/spec/rails-app-3.2.14/public/422.html +26 -0
- data/spec/rails-app-3.2.14/public/500.html +25 -0
- data/spec/rails-app-3.2.14/public/favicon.ico +0 -0
- data/spec/rails-app-3.2.14/public/robots.txt +5 -0
- data/spec/rails-app-3.2.14/script/rails +6 -0
- data/spec/rails-app-3.2.14/vendor/assets/javascripts/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/vendor/assets/stylesheets/.gitkeep +0 -0
- data/spec/rails-app-3.2.14/vendor/plugins/.gitkeep +0 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/views/analytics-js/_loader.html.erb_spec.rb +15 -0
- data/spec/views/layouts/application.html.erb_spec.rb +11 -0
- metadata +143 -8
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Analytics.js-Rails
|
2
2
|
|
3
|
-
|
3
|
+
This gem packages a self-hosted copy of [Analytics.js](https://github.com/segmentio/analytics.js), a wrapper for web analytics services, for use with the Ruby on Rails 3.1+ asset pipeline.
|
4
4
|
|
5
|
-
Service A is good at X
|
5
|
+
The unfortunate truch: Analytics Service A is good at X, bad at Y, Analytics Service B is good at Y, bad at X and Z. Or maybe Marketing likes Service A, but Engineering needs Service B. Whatever. Analytics.js offers one common interface to standardize and modularize analytics setup across services - now easily in rails.
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -20,26 +20,33 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Usage
|
22
22
|
|
23
|
-
|
23
|
+
Render the loader partial on all pages where you want Analytics.js to load. Typically this is done in application.html.erb, immediately after the opening <body> tag. For example:
|
24
24
|
|
25
|
-
<%= render 'analytics-js/loader',
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
<%= render 'analytics-js/loader',
|
26
|
+
user_identifier: current_user.id,
|
27
|
+
providers: {
|
28
|
+
'Google Analytics' => 'google_analytics_key',
|
29
|
+
'KISSmetrics' => 'kissmetrics_key'
|
30
|
+
} %>
|
29
31
|
|
30
32
|
Of course, keys should probably be stored in config files, not hard coded.
|
31
33
|
|
34
|
+
Make sure that you ```root :to => "controller#action"``` in ```config/routes.rb```.
|
35
|
+
|
32
36
|
Add to your ```config/environments/production.rb```:
|
33
37
|
|
34
38
|
config.assets.precompile += %w( analytics.js )
|
35
39
|
|
36
|
-
|
37
|
-
You can now use rickshaw in your app.
|
40
|
+
You can now use Analytics.js in your app.
|
38
41
|
|
39
42
|
## Version
|
40
43
|
|
41
44
|
The version of this gem reflects the Analytics.js version.
|
42
45
|
|
46
|
+
## Thanks
|
47
|
+
|
48
|
+
To the folks at [segment.io](http://segment.io) for all their work on Analytics.js - to a more panoptical world!
|
49
|
+
|
43
50
|
## Contributing
|
44
51
|
|
45
52
|
Yes, please. Pull requests are very welcome. If it's not tested, we will not pull it.
|
data/analytics-js-rails.gemspec
CHANGED
@@ -18,8 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "railties", ">= 3.1.0"
|
21
|
+
spec.add_dependency "railties", ">= 3.1.0", "<4.0.0"
|
22
22
|
spec.add_development_dependency "bundler", ">= 1.0.0"
|
23
23
|
spec.add_development_dependency "rake"
|
24
|
-
spec.add_development_dependency "
|
24
|
+
spec.add_development_dependency "rails", ">= 3.1.0", "<4.0.0"
|
25
|
+
spec.add_development_dependency "rspec-rails"
|
25
26
|
end
|
@@ -1591,10 +1591,10 @@ require.register("segmentio-store.js/store.js", function(exports, require, modul
|
|
1591
1591
|
var json = require('json')
|
1592
1592
|
, store = {}
|
1593
1593
|
, win = window
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
1597
|
-
|
1594
|
+
, doc = win.document
|
1595
|
+
, localStorageName = 'localStorage'
|
1596
|
+
, namespace = '__storejs__'
|
1597
|
+
, storage;
|
1598
1598
|
|
1599
1599
|
store.disabled = false
|
1600
1600
|
store.set = function(key, value) {}
|
@@ -1602,139 +1602,139 @@ store.get = function(key) {}
|
|
1602
1602
|
store.remove = function(key) {}
|
1603
1603
|
store.clear = function() {}
|
1604
1604
|
store.transact = function(key, defaultVal, transactionFn) {
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
|
1609
|
-
|
1610
|
-
|
1611
|
-
|
1612
|
-
|
1605
|
+
var val = store.get(key)
|
1606
|
+
if (transactionFn == null) {
|
1607
|
+
transactionFn = defaultVal
|
1608
|
+
defaultVal = null
|
1609
|
+
}
|
1610
|
+
if (typeof val == 'undefined') { val = defaultVal || {} }
|
1611
|
+
transactionFn(val)
|
1612
|
+
store.set(key, val)
|
1613
1613
|
}
|
1614
1614
|
store.getAll = function() {}
|
1615
1615
|
|
1616
1616
|
store.serialize = function(value) {
|
1617
|
-
|
1617
|
+
return json.stringify(value)
|
1618
1618
|
}
|
1619
1619
|
store.deserialize = function(value) {
|
1620
|
-
|
1621
|
-
|
1622
|
-
|
1620
|
+
if (typeof value != 'string') { return undefined }
|
1621
|
+
try { return json.parse(value) }
|
1622
|
+
catch(e) { return value || undefined }
|
1623
1623
|
}
|
1624
1624
|
|
1625
1625
|
// Functions to encapsulate questionable FireFox 3.6.13 behavior
|
1626
1626
|
// when about.config::dom.storage.enabled === false
|
1627
1627
|
// See https://github.com/marcuswestin/store.js/issues#issue/13
|
1628
1628
|
function isLocalStorageNameSupported() {
|
1629
|
-
|
1630
|
-
|
1629
|
+
try { return (localStorageName in win && win[localStorageName]) }
|
1630
|
+
catch(err) { return false }
|
1631
1631
|
}
|
1632
1632
|
|
1633
1633
|
if (isLocalStorageNameSupported()) {
|
1634
|
-
|
1635
|
-
|
1636
|
-
|
1637
|
-
|
1638
|
-
|
1639
|
-
|
1640
|
-
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1634
|
+
storage = win[localStorageName]
|
1635
|
+
store.set = function(key, val) {
|
1636
|
+
if (val === undefined) { return store.remove(key) }
|
1637
|
+
storage.setItem(key, store.serialize(val))
|
1638
|
+
return val
|
1639
|
+
}
|
1640
|
+
store.get = function(key) { return store.deserialize(storage.getItem(key)) }
|
1641
|
+
store.remove = function(key) { storage.removeItem(key) }
|
1642
|
+
store.clear = function() { storage.clear() }
|
1643
|
+
store.getAll = function() {
|
1644
|
+
var ret = {}
|
1645
|
+
for (var i=0; i<storage.length; ++i) {
|
1646
|
+
var key = storage.key(i)
|
1647
|
+
ret[key] = store.get(key)
|
1648
|
+
}
|
1649
|
+
return ret
|
1650
|
+
}
|
1651
1651
|
} else if (doc.documentElement.addBehavior) {
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
1672
|
-
|
1673
|
-
|
1674
|
-
|
1675
|
-
|
1676
|
-
|
1677
|
-
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1687
|
-
|
1688
|
-
|
1689
|
-
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1693
|
-
|
1694
|
-
|
1695
|
-
|
1696
|
-
|
1697
|
-
|
1698
|
-
|
1699
|
-
|
1700
|
-
|
1701
|
-
|
1702
|
-
|
1703
|
-
|
1704
|
-
|
1705
|
-
|
1706
|
-
|
1707
|
-
|
1708
|
-
|
1709
|
-
|
1710
|
-
|
1711
|
-
|
1712
|
-
|
1713
|
-
|
1714
|
-
|
1715
|
-
|
1716
|
-
|
1717
|
-
|
1718
|
-
|
1719
|
-
|
1720
|
-
|
1721
|
-
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1727
|
-
|
1728
|
-
|
1729
|
-
|
1652
|
+
var storageOwner,
|
1653
|
+
storageContainer
|
1654
|
+
// Since #userData storage applies only to specific paths, we need to
|
1655
|
+
// somehow link our data to a specific path. We choose /favicon.ico
|
1656
|
+
// as a pretty safe option, since all browsers already make a request to
|
1657
|
+
// this URL anyway and being a 404 will not hurt us here. We wrap an
|
1658
|
+
// iframe pointing to the favicon in an ActiveXObject(htmlfile) object
|
1659
|
+
// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
|
1660
|
+
// since the iframe access rules appear to allow direct access and
|
1661
|
+
// manipulation of the document element, even for a 404 page. This
|
1662
|
+
// document can be used instead of the current document (which would
|
1663
|
+
// have been limited to the current path) to perform #userData storage.
|
1664
|
+
try {
|
1665
|
+
storageContainer = new ActiveXObject('htmlfile')
|
1666
|
+
storageContainer.open()
|
1667
|
+
storageContainer.write('<s' + 'cript>document.w=window</s' + 'cript><iframe src="/favicon.ico"></iframe>')
|
1668
|
+
storageContainer.close()
|
1669
|
+
storageOwner = storageContainer.w.frames[0].document
|
1670
|
+
storage = storageOwner.createElement('div')
|
1671
|
+
} catch(e) {
|
1672
|
+
// somehow ActiveXObject instantiation failed (perhaps some special
|
1673
|
+
// security settings or otherwse), fall back to per-path storage
|
1674
|
+
storage = doc.createElement('div')
|
1675
|
+
storageOwner = doc.body
|
1676
|
+
}
|
1677
|
+
function withIEStorage(storeFunction) {
|
1678
|
+
return function() {
|
1679
|
+
var args = Array.prototype.slice.call(arguments, 0)
|
1680
|
+
args.unshift(storage)
|
1681
|
+
// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
|
1682
|
+
// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
|
1683
|
+
storageOwner.appendChild(storage)
|
1684
|
+
storage.addBehavior('#default#userData')
|
1685
|
+
storage.load(localStorageName)
|
1686
|
+
var result = storeFunction.apply(store, args)
|
1687
|
+
storageOwner.removeChild(storage)
|
1688
|
+
return result
|
1689
|
+
}
|
1690
|
+
}
|
1691
|
+
|
1692
|
+
// In IE7, keys may not contain special chars. See all of https://github.com/marcuswestin/store.js/issues/40
|
1693
|
+
var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
|
1694
|
+
function ieKeyFix(key) {
|
1695
|
+
return key.replace(forbiddenCharsRegex, '___')
|
1696
|
+
}
|
1697
|
+
store.set = withIEStorage(function(storage, key, val) {
|
1698
|
+
key = ieKeyFix(key)
|
1699
|
+
if (val === undefined) { return store.remove(key) }
|
1700
|
+
storage.setAttribute(key, store.serialize(val))
|
1701
|
+
storage.save(localStorageName)
|
1702
|
+
return val
|
1703
|
+
})
|
1704
|
+
store.get = withIEStorage(function(storage, key) {
|
1705
|
+
key = ieKeyFix(key)
|
1706
|
+
return store.deserialize(storage.getAttribute(key))
|
1707
|
+
})
|
1708
|
+
store.remove = withIEStorage(function(storage, key) {
|
1709
|
+
key = ieKeyFix(key)
|
1710
|
+
storage.removeAttribute(key)
|
1711
|
+
storage.save(localStorageName)
|
1712
|
+
})
|
1713
|
+
store.clear = withIEStorage(function(storage) {
|
1714
|
+
var attributes = storage.XMLDocument.documentElement.attributes
|
1715
|
+
storage.load(localStorageName)
|
1716
|
+
for (var i=0, attr; attr=attributes[i]; i++) {
|
1717
|
+
storage.removeAttribute(attr.name)
|
1718
|
+
}
|
1719
|
+
storage.save(localStorageName)
|
1720
|
+
})
|
1721
|
+
store.getAll = withIEStorage(function(storage) {
|
1722
|
+
var attributes = storage.XMLDocument.documentElement.attributes
|
1723
|
+
var ret = {}
|
1724
|
+
for (var i=0, attr; attr=attributes[i]; ++i) {
|
1725
|
+
var key = ieKeyFix(attr.name)
|
1726
|
+
ret[attr.name] = store.deserialize(storage.getAttribute(key))
|
1727
|
+
}
|
1728
|
+
return ret
|
1729
|
+
})
|
1730
1730
|
}
|
1731
1731
|
|
1732
1732
|
try {
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1733
|
+
store.set(namespace, namespace)
|
1734
|
+
if (store.get(namespace) != namespace) { store.disabled = true }
|
1735
|
+
store.remove(namespace)
|
1736
1736
|
} catch(e) {
|
1737
|
-
|
1737
|
+
store.disabled = true
|
1738
1738
|
}
|
1739
1739
|
store.enabled = !store.disabled
|
1740
1740
|
|
@@ -3570,75 +3570,75 @@ module.exports = Provider.extend({
|
|
3570
3570
|
});
|
3571
3571
|
});
|
3572
3572
|
require.register("analytics/src/providers/foxmetrics.js", function(exports, require, module){
|
3573
|
-
// http://foxmetrics.com/documentation/apijavascript
|
3574
|
-
|
3575
|
-
var Provider = require('../provider')
|
3576
|
-
, load = require('load-script');
|
3577
|
-
|
3578
|
-
|
3579
|
-
module.exports = Provider.extend({
|
3580
|
-
|
3581
|
-
name : 'FoxMetrics',
|
3582
|
-
|
3583
|
-
key : 'appId',
|
3584
|
-
|
3585
|
-
defaults : {
|
3586
|
-
appId : null
|
3587
|
-
},
|
3588
|
-
|
3589
|
-
initialize : function (options, ready) {
|
3590
|
-
var _fxm = window._fxm || {};
|
3591
|
-
window._fxm = _fxm.events || [];
|
3592
|
-
load('//d35tca7vmefkrc.cloudfront.net/scripts/' + options.appId + '.js');
|
3593
|
-
|
3594
|
-
// FoxMetrics makes a queue, so it's ready immediately.
|
3595
|
-
ready();
|
3596
|
-
},
|
3597
|
-
|
3598
|
-
identify : function (userId, traits) {
|
3599
|
-
// A `userId` is required for profile updates.
|
3600
|
-
if (!userId) return;
|
3601
|
-
|
3602
|
-
// FoxMetrics needs the first and last name seperately. Fallback to
|
3603
|
-
// splitting the `name` trait if we don't have what we need.
|
3604
|
-
var firstName = traits.firstName
|
3605
|
-
, lastName = traits.lastName;
|
3606
|
-
|
3607
|
-
if (!firstName && traits.name) firstName = traits.name.split(' ')[0];
|
3608
|
-
if (!lastName && traits.name) lastName = traits.name.split(' ')[1];
|
3609
|
-
|
3610
|
-
window._fxm.push([
|
3611
|
-
'_fxm.visitor.profile',
|
3612
|
-
userId, // user id
|
3613
|
-
firstName, // first name
|
3614
|
-
lastName, // last name
|
3615
|
-
traits.email, // email
|
3616
|
-
traits.address, // address
|
3617
|
-
undefined, // social
|
3618
|
-
undefined, // partners
|
3619
|
-
traits // attributes
|
3620
|
-
]);
|
3621
|
-
},
|
3622
|
-
|
3623
|
-
track : function (event, properties) {
|
3624
|
-
window._fxm.push([
|
3625
|
-
event, // event name
|
3626
|
-
properties.category, // category
|
3627
|
-
properties // properties
|
3628
|
-
]);
|
3629
|
-
},
|
3630
|
-
|
3631
|
-
pageview : function (url) {
|
3632
|
-
window._fxm.push([
|
3633
|
-
'_fxm.pages.view',
|
3634
|
-
undefined, // title
|
3635
|
-
undefined, // name
|
3636
|
-
undefined, // category
|
3637
|
-
url, // url
|
3638
|
-
undefined // referrer
|
3639
|
-
]);
|
3640
|
-
}
|
3641
|
-
|
3573
|
+
// http://foxmetrics.com/documentation/apijavascript
|
3574
|
+
|
3575
|
+
var Provider = require('../provider')
|
3576
|
+
, load = require('load-script');
|
3577
|
+
|
3578
|
+
|
3579
|
+
module.exports = Provider.extend({
|
3580
|
+
|
3581
|
+
name : 'FoxMetrics',
|
3582
|
+
|
3583
|
+
key : 'appId',
|
3584
|
+
|
3585
|
+
defaults : {
|
3586
|
+
appId : null
|
3587
|
+
},
|
3588
|
+
|
3589
|
+
initialize : function (options, ready) {
|
3590
|
+
var _fxm = window._fxm || {};
|
3591
|
+
window._fxm = _fxm.events || [];
|
3592
|
+
load('//d35tca7vmefkrc.cloudfront.net/scripts/' + options.appId + '.js');
|
3593
|
+
|
3594
|
+
// FoxMetrics makes a queue, so it's ready immediately.
|
3595
|
+
ready();
|
3596
|
+
},
|
3597
|
+
|
3598
|
+
identify : function (userId, traits) {
|
3599
|
+
// A `userId` is required for profile updates.
|
3600
|
+
if (!userId) return;
|
3601
|
+
|
3602
|
+
// FoxMetrics needs the first and last name seperately. Fallback to
|
3603
|
+
// splitting the `name` trait if we don't have what we need.
|
3604
|
+
var firstName = traits.firstName
|
3605
|
+
, lastName = traits.lastName;
|
3606
|
+
|
3607
|
+
if (!firstName && traits.name) firstName = traits.name.split(' ')[0];
|
3608
|
+
if (!lastName && traits.name) lastName = traits.name.split(' ')[1];
|
3609
|
+
|
3610
|
+
window._fxm.push([
|
3611
|
+
'_fxm.visitor.profile',
|
3612
|
+
userId, // user id
|
3613
|
+
firstName, // first name
|
3614
|
+
lastName, // last name
|
3615
|
+
traits.email, // email
|
3616
|
+
traits.address, // address
|
3617
|
+
undefined, // social
|
3618
|
+
undefined, // partners
|
3619
|
+
traits // attributes
|
3620
|
+
]);
|
3621
|
+
},
|
3622
|
+
|
3623
|
+
track : function (event, properties) {
|
3624
|
+
window._fxm.push([
|
3625
|
+
event, // event name
|
3626
|
+
properties.category, // category
|
3627
|
+
properties // properties
|
3628
|
+
]);
|
3629
|
+
},
|
3630
|
+
|
3631
|
+
pageview : function (url) {
|
3632
|
+
window._fxm.push([
|
3633
|
+
'_fxm.pages.view',
|
3634
|
+
undefined, // title
|
3635
|
+
undefined, // name
|
3636
|
+
undefined, // category
|
3637
|
+
url, // url
|
3638
|
+
undefined // referrer
|
3639
|
+
]);
|
3640
|
+
}
|
3641
|
+
|
3642
3642
|
});
|
3643
3643
|
});
|
3644
3644
|
require.register("analytics/src/providers/gauges.js", function(exports, require, module){
|
@@ -3784,4 +3784,1795 @@ module.exports = Provider.extend({
|
|
3784
3784
|
}
|
3785
3785
|
if (options.initialPageview) {
|
3786
3786
|
var path, canon = canonical();
|
3787
|
-
if (canon)
|
3787
|
+
if (canon) path = url.parse(canon).pathname;
|
3788
|
+
this.pageview(path);
|
3789
|
+
}
|
3790
|
+
|
3791
|
+
// URLs change if DoubleClick is on. Even though Google Analytics makes a
|
3792
|
+
// queue, the `_gat` object isn't available until the library loads.
|
3793
|
+
if (options.doubleClick) {
|
3794
|
+
load('//stats.g.doubleclick.net/dc.js', ready);
|
3795
|
+
} else {
|
3796
|
+
load({
|
3797
|
+
http : 'http://www.google-analytics.com/ga.js',
|
3798
|
+
https : 'https://ssl.google-analytics.com/ga.js'
|
3799
|
+
}, ready);
|
3800
|
+
}
|
3801
|
+
},
|
3802
|
+
|
3803
|
+
initializeUniversal: function (options, ready) {
|
3804
|
+
|
3805
|
+
// GA-universal lets you set your own queue name
|
3806
|
+
var global = this.global = 'ga';
|
3807
|
+
|
3808
|
+
// and needs to know about this queue name in this special object
|
3809
|
+
// so that future plugins can also operate on the object
|
3810
|
+
window['GoogleAnalyticsObject'] = global;
|
3811
|
+
|
3812
|
+
// setup the global variable
|
3813
|
+
window[global] = window[global] || function () {
|
3814
|
+
(window[global].q = window[global].q || []).push(arguments);
|
3815
|
+
};
|
3816
|
+
|
3817
|
+
// GA also needs to know the current time (all from their snippet)
|
3818
|
+
window[global].l = 1 * new Date();
|
3819
|
+
|
3820
|
+
var createOpts = {};
|
3821
|
+
|
3822
|
+
// Apply a bunch of optional settings.
|
3823
|
+
if (options.domain)
|
3824
|
+
createOpts.cookieDomain = options.domain || 'none';
|
3825
|
+
if (type(options.siteSpeedSampleRate) === 'number')
|
3826
|
+
createOpts.siteSpeedSampleRate = options.siteSpeedSampleRate;
|
3827
|
+
if (options.anonymizeIp)
|
3828
|
+
ga('set', 'anonymizeIp', true);
|
3829
|
+
|
3830
|
+
ga('create', options.trackingId, createOpts);
|
3831
|
+
|
3832
|
+
if (options.initialPageview) {
|
3833
|
+
var path, canon = canonical();
|
3834
|
+
if (canon) path = url.parse(canon).pathname;
|
3835
|
+
this.pageview(path);
|
3836
|
+
}
|
3837
|
+
|
3838
|
+
load('//www.google-analytics.com/analytics.js');
|
3839
|
+
|
3840
|
+
// Google makes a queue so it's ready immediately.
|
3841
|
+
ready();
|
3842
|
+
},
|
3843
|
+
|
3844
|
+
track : function (event, properties) {
|
3845
|
+
properties || (properties = {});
|
3846
|
+
|
3847
|
+
var value;
|
3848
|
+
|
3849
|
+
// Since value is a common property name, ensure it is a number and Google
|
3850
|
+
// requires that it be an integer.
|
3851
|
+
if (type(properties.value) === 'number') value = Math.round(properties.value);
|
3852
|
+
|
3853
|
+
// Try to check for a `category` and `label`. A `category` is required,
|
3854
|
+
// so if it's not there we use `'All'` as a default. We can safely push
|
3855
|
+
// undefined if the special properties don't exist. Try using revenue
|
3856
|
+
// first, but fall back to a generic `value` as well.
|
3857
|
+
if (this.options.universalClient) {
|
3858
|
+
var opts = {};
|
3859
|
+
if (properties.noninteraction) opts.nonInteraction = properties.noninteraction;
|
3860
|
+
window[this.global](
|
3861
|
+
'send',
|
3862
|
+
'event',
|
3863
|
+
properties.category || 'All',
|
3864
|
+
event,
|
3865
|
+
properties.label,
|
3866
|
+
Math.round(properties.revenue) || value,
|
3867
|
+
opts
|
3868
|
+
);
|
3869
|
+
} else {
|
3870
|
+
window._gaq.push([
|
3871
|
+
'_trackEvent',
|
3872
|
+
properties.category || 'All',
|
3873
|
+
event,
|
3874
|
+
properties.label,
|
3875
|
+
Math.round(properties.revenue) || value,
|
3876
|
+
properties.noninteraction
|
3877
|
+
]);
|
3878
|
+
}
|
3879
|
+
},
|
3880
|
+
|
3881
|
+
pageview : function (url) {
|
3882
|
+
if (this.options.universalClient) {
|
3883
|
+
window[this.global]('send', 'pageview', url);
|
3884
|
+
} else {
|
3885
|
+
window._gaq.push(['_trackPageview', url]);
|
3886
|
+
}
|
3887
|
+
}
|
3888
|
+
|
3889
|
+
});
|
3890
|
+
});
|
3891
|
+
require.register("analytics/src/providers/gosquared.js", function(exports, require, module){
|
3892
|
+
// http://www.gosquared.com/support
|
3893
|
+
// https://www.gosquared.com/customer/portal/articles/612063-tracker-functions
|
3894
|
+
|
3895
|
+
var Provider = require('../provider')
|
3896
|
+
, user = require('../user')
|
3897
|
+
, load = require('load-script')
|
3898
|
+
, onBody = require('on-body');
|
3899
|
+
|
3900
|
+
|
3901
|
+
module.exports = Provider.extend({
|
3902
|
+
|
3903
|
+
name : 'GoSquared',
|
3904
|
+
|
3905
|
+
key : 'siteToken',
|
3906
|
+
|
3907
|
+
defaults : {
|
3908
|
+
siteToken : null
|
3909
|
+
},
|
3910
|
+
|
3911
|
+
initialize : function (options, ready) {
|
3912
|
+
// GoSquared assumes a body in their script, so we need this wrapper.
|
3913
|
+
onBody(function () {
|
3914
|
+
var GoSquared = window.GoSquared = {};
|
3915
|
+
GoSquared.acct = options.siteToken;
|
3916
|
+
GoSquared.q = [];
|
3917
|
+
window._gstc_lt =+ (new Date());
|
3918
|
+
|
3919
|
+
GoSquared.VisitorName = user.id();
|
3920
|
+
GoSquared.Visitor = user.traits();
|
3921
|
+
|
3922
|
+
load('//d1l6p2sc9645hc.cloudfront.net/tracker.js');
|
3923
|
+
|
3924
|
+
// GoSquared makes a queue, so it's ready immediately.
|
3925
|
+
ready();
|
3926
|
+
});
|
3927
|
+
},
|
3928
|
+
|
3929
|
+
identify : function (userId, traits) {
|
3930
|
+
// TODO figure out if this will actually work. Seems like GoSquared will
|
3931
|
+
// never know these values are updated.
|
3932
|
+
if (userId) window.GoSquared.UserName = userId;
|
3933
|
+
if (traits) window.GoSquared.Visitor = traits;
|
3934
|
+
},
|
3935
|
+
|
3936
|
+
track : function (event, properties) {
|
3937
|
+
// GoSquared sets a `gs_evt_name` property with a value of the event
|
3938
|
+
// name, so it relies on properties being an object.
|
3939
|
+
window.GoSquared.q.push(['TrackEvent', event, properties || {}]);
|
3940
|
+
},
|
3941
|
+
|
3942
|
+
pageview : function (url) {
|
3943
|
+
window.GoSquared.q.push(['TrackView', url]);
|
3944
|
+
}
|
3945
|
+
|
3946
|
+
});
|
3947
|
+
});
|
3948
|
+
require.register("analytics/src/providers/heap.js", function(exports, require, module){
|
3949
|
+
// https://heapanalytics.com/docs
|
3950
|
+
|
3951
|
+
var Provider = require('../provider')
|
3952
|
+
, load = require('load-script');
|
3953
|
+
|
3954
|
+
module.exports = Provider.extend({
|
3955
|
+
|
3956
|
+
name : 'Heap',
|
3957
|
+
|
3958
|
+
key : 'apiKey',
|
3959
|
+
|
3960
|
+
defaults : {
|
3961
|
+
apiKey : null
|
3962
|
+
},
|
3963
|
+
|
3964
|
+
initialize : function (options, ready) {
|
3965
|
+
window.heap=window.heap||[];window.heap.load=function(a){window._heapid=a;var b=document.createElement("script");b.type="text/javascript",b.async=!0,b.src=("https:"===document.location.protocol?"https:":"http:")+"//d36lvucg9kzous.cloudfront.net";var c=document.getElementsByTagName("script")[0];c.parentNode.insertBefore(b,c);var d=function(a){return function(){heap.push([a].concat(Array.prototype.slice.call(arguments,0)))}},e=["identify","track"];for(var f=0;f<e.length;f++)heap[e[f]]=d(e[f])};
|
3966
|
+
window.heap.load(options.apiKey);
|
3967
|
+
|
3968
|
+
// heap creates its own queue, so we're ready right away
|
3969
|
+
ready();
|
3970
|
+
},
|
3971
|
+
|
3972
|
+
identify : function (userId, traits) {
|
3973
|
+
window.heap.identify(traits);
|
3974
|
+
},
|
3975
|
+
|
3976
|
+
track : function (event, properties) {
|
3977
|
+
window.heap.track(event, properties);
|
3978
|
+
}
|
3979
|
+
|
3980
|
+
});
|
3981
|
+
});
|
3982
|
+
require.register("analytics/src/providers/hittail.js", function(exports, require, module){
|
3983
|
+
// http://www.hittail.com
|
3984
|
+
|
3985
|
+
var Provider = require('../provider')
|
3986
|
+
, load = require('load-script');
|
3987
|
+
|
3988
|
+
|
3989
|
+
module.exports = Provider.extend({
|
3990
|
+
|
3991
|
+
name : 'HitTail',
|
3992
|
+
|
3993
|
+
key : 'siteId',
|
3994
|
+
|
3995
|
+
defaults : {
|
3996
|
+
siteId : null
|
3997
|
+
},
|
3998
|
+
|
3999
|
+
initialize : function (options, ready) {
|
4000
|
+
load('//' + options.siteId + '.hittail.com/mlt.js', ready);
|
4001
|
+
}
|
4002
|
+
|
4003
|
+
});
|
4004
|
+
});
|
4005
|
+
require.register("analytics/src/providers/hubspot.js", function(exports, require, module){
|
4006
|
+
// http://hubspot.clarify-it.com/d/4m62hl
|
4007
|
+
|
4008
|
+
var Provider = require('../provider')
|
4009
|
+
, isEmail = require('is-email')
|
4010
|
+
, load = require('load-script');
|
4011
|
+
|
4012
|
+
|
4013
|
+
module.exports = Provider.extend({
|
4014
|
+
|
4015
|
+
name : 'HubSpot',
|
4016
|
+
|
4017
|
+
key : 'portalId',
|
4018
|
+
|
4019
|
+
defaults : {
|
4020
|
+
portalId : null
|
4021
|
+
},
|
4022
|
+
|
4023
|
+
initialize : function (options, ready) {
|
4024
|
+
// HubSpot checks in their snippet to make sure another script with
|
4025
|
+
// `hs-analytics` isn't already in the DOM. Seems excessive, but who knows
|
4026
|
+
// if there's weird deprecation going on :p
|
4027
|
+
if (!document.getElementById('hs-analytics')) {
|
4028
|
+
window._hsq = window._hsq || [];
|
4029
|
+
var script = load('https://js.hubspot.com/analytics/' + (Math.ceil(new Date()/300000)*300000) + '/' + options.portalId + '.js');
|
4030
|
+
script.id = 'hs-analytics';
|
4031
|
+
}
|
4032
|
+
|
4033
|
+
// HubSpot makes a queue, so it's ready immediately.
|
4034
|
+
ready();
|
4035
|
+
},
|
4036
|
+
|
4037
|
+
// HubSpot does not use a userId, but the email address is required on
|
4038
|
+
// the traits object.
|
4039
|
+
identify : function (userId, traits) {
|
4040
|
+
window._hsq.push(["identify", traits]);
|
4041
|
+
},
|
4042
|
+
|
4043
|
+
// Event Tracking is available to HubSpot Enterprise customers only. In
|
4044
|
+
// addition to adding any unique event name, you can also use the id of an
|
4045
|
+
// existing custom event as the event variable.
|
4046
|
+
track : function (event, properties) {
|
4047
|
+
window._hsq.push(["trackEvent", event, properties]);
|
4048
|
+
},
|
4049
|
+
|
4050
|
+
// HubSpot doesn't support passing in a custom URL.
|
4051
|
+
pageview : function (url) {
|
4052
|
+
window._hsq.push(['_trackPageview']);
|
4053
|
+
}
|
4054
|
+
|
4055
|
+
});
|
4056
|
+
});
|
4057
|
+
require.register("analytics/src/providers/index.js", function(exports, require, module){
|
4058
|
+
module.exports = [
|
4059
|
+
require('./adroll'),
|
4060
|
+
require('./amplitude'),
|
4061
|
+
require('./bitdeli'),
|
4062
|
+
require('./bugherd'),
|
4063
|
+
require('./chartbeat'),
|
4064
|
+
require('./clicktale'),
|
4065
|
+
require('./clicky'),
|
4066
|
+
require('./comscore'),
|
4067
|
+
require('./crazyegg'),
|
4068
|
+
require('./customerio'),
|
4069
|
+
require('./errorception'),
|
4070
|
+
require('./foxmetrics'),
|
4071
|
+
require('./gauges'),
|
4072
|
+
require('./get-satisfaction'),
|
4073
|
+
require('./google-analytics'),
|
4074
|
+
require('./gosquared'),
|
4075
|
+
require('./heap'),
|
4076
|
+
require('./hittail'),
|
4077
|
+
require('./hubspot'),
|
4078
|
+
require('./improvely'),
|
4079
|
+
require('./intercom'),
|
4080
|
+
require('./keen-io'),
|
4081
|
+
require('./kissmetrics'),
|
4082
|
+
require('./klaviyo'),
|
4083
|
+
require('./livechat'),
|
4084
|
+
require('./lytics'),
|
4085
|
+
require('./mixpanel'),
|
4086
|
+
require('./olark'),
|
4087
|
+
require('./optimizely'),
|
4088
|
+
require('./perfect-audience'),
|
4089
|
+
require('./pingdom'),
|
4090
|
+
require('./preact'),
|
4091
|
+
require('./qualaroo'),
|
4092
|
+
require('./quantcast'),
|
4093
|
+
require('./sentry'),
|
4094
|
+
require('./snapengage'),
|
4095
|
+
require('./usercycle'),
|
4096
|
+
require('./userfox'),
|
4097
|
+
require('./uservoice'),
|
4098
|
+
require('./vero'),
|
4099
|
+
require('./visual-website-optimizer'),
|
4100
|
+
require('./woopra')
|
4101
|
+
];
|
4102
|
+
|
4103
|
+
});
|
4104
|
+
require.register("analytics/src/providers/improvely.js", function(exports, require, module){
|
4105
|
+
// http://www.improvely.com/docs/landing-page-code
|
4106
|
+
// http://www.improvely.com/docs/conversion-code
|
4107
|
+
// http://www.improvely.com/docs/labeling-visitors
|
4108
|
+
|
4109
|
+
var Provider = require('../provider')
|
4110
|
+
, alias = require('alias')
|
4111
|
+
, load = require('load-script');
|
4112
|
+
|
4113
|
+
|
4114
|
+
module.exports = Provider.extend({
|
4115
|
+
|
4116
|
+
name : 'Improvely',
|
4117
|
+
|
4118
|
+
defaults : {
|
4119
|
+
// Improvely requires two options: `domain` and `projectId`.
|
4120
|
+
domain : null,
|
4121
|
+
projectId : null
|
4122
|
+
},
|
4123
|
+
|
4124
|
+
initialize : function (options, ready) {
|
4125
|
+
window._improvely = window._improvely || [];
|
4126
|
+
window.improvely = window.improvely || {
|
4127
|
+
init : function (e, t) { window._improvely.push(["init", e, t]); },
|
4128
|
+
goal : function (e) { window._improvely.push(["goal", e]); },
|
4129
|
+
label : function (e) { window._improvely.push(["label", e]); }
|
4130
|
+
};
|
4131
|
+
|
4132
|
+
load('//' + options.domain + '.iljmp.com/improvely.js');
|
4133
|
+
window.improvely.init(options.domain, options.projectId);
|
4134
|
+
|
4135
|
+
// Improvely creates a queue, so it's ready immediately.
|
4136
|
+
ready();
|
4137
|
+
},
|
4138
|
+
|
4139
|
+
identify : function (userId, traits) {
|
4140
|
+
if (userId) window.improvely.label(userId);
|
4141
|
+
},
|
4142
|
+
|
4143
|
+
track : function (event, properties) {
|
4144
|
+
// Improvely calls `revenue` `amount`, and puts the `event` in properties as
|
4145
|
+
// the `type`.
|
4146
|
+
properties || (properties = {});
|
4147
|
+
properties.type = event;
|
4148
|
+
alias(properties, { 'revenue' : 'amount' });
|
4149
|
+
window.improvely.goal(properties);
|
4150
|
+
}
|
4151
|
+
|
4152
|
+
});
|
4153
|
+
|
4154
|
+
});
|
4155
|
+
require.register("analytics/src/providers/intercom.js", function(exports, require, module){
|
4156
|
+
// http://docs.intercom.io/
|
4157
|
+
// http://docs.intercom.io/#IntercomJS
|
4158
|
+
|
4159
|
+
var Provider = require('../provider')
|
4160
|
+
, extend = require('extend')
|
4161
|
+
, load = require('load-script')
|
4162
|
+
, isEmail = require('is-email');
|
4163
|
+
|
4164
|
+
|
4165
|
+
module.exports = Provider.extend({
|
4166
|
+
|
4167
|
+
name : 'Intercom',
|
4168
|
+
|
4169
|
+
// Whether Intercom has already been booted or not. Intercom becomes booted
|
4170
|
+
// after Intercom('boot', ...) has been called on the first identify.
|
4171
|
+
booted : false,
|
4172
|
+
|
4173
|
+
key : 'appId',
|
4174
|
+
|
4175
|
+
defaults : {
|
4176
|
+
// Intercom's required key.
|
4177
|
+
appId : null,
|
4178
|
+
// An optional setting to display the Intercom inbox widget.
|
4179
|
+
activator : null,
|
4180
|
+
// Whether to show the count of messages for the inbox widget.
|
4181
|
+
counter : true
|
4182
|
+
},
|
4183
|
+
|
4184
|
+
initialize : function (options, ready) {
|
4185
|
+
load('https://static.intercomcdn.com/intercom.v1.js', ready);
|
4186
|
+
},
|
4187
|
+
|
4188
|
+
identify : function (userId, traits, options) {
|
4189
|
+
// Don't do anything if we just have traits the first time.
|
4190
|
+
if (!this.booted && !userId) return;
|
4191
|
+
|
4192
|
+
// Intercom specific settings. BACKWARDS COMPATIBILITY: we need to check for
|
4193
|
+
// the lowercase variant as well.
|
4194
|
+
options || (options = {});
|
4195
|
+
var Intercom = options.Intercom || options.intercom || {};
|
4196
|
+
traits.increments = Intercom.increments;
|
4197
|
+
traits.user_hash = Intercom.userHash || Intercom.user_hash;
|
4198
|
+
|
4199
|
+
// They need `created_at` as a Unix timestamp (seconds).
|
4200
|
+
if (traits.created) {
|
4201
|
+
traits.created_at = Math.floor(traits.created/1000);
|
4202
|
+
delete traits.created;
|
4203
|
+
}
|
4204
|
+
|
4205
|
+
// Convert a `company`'s `created` date.
|
4206
|
+
if (traits.company && traits.company.created) {
|
4207
|
+
traits.company.created_at = Math.floor(traits.company.created/1000);
|
4208
|
+
delete traits.company.created;
|
4209
|
+
}
|
4210
|
+
|
4211
|
+
// Optionally add the inbox widget.
|
4212
|
+
if (this.options.activator) {
|
4213
|
+
traits.widget = {
|
4214
|
+
activator : this.options.activator,
|
4215
|
+
use_counter : this.options.counter
|
4216
|
+
};
|
4217
|
+
}
|
4218
|
+
|
4219
|
+
// If this is the first time we've identified, `boot` instead of `update`
|
4220
|
+
// and add our one-time boot settings.
|
4221
|
+
if (this.booted) {
|
4222
|
+
window.Intercom('update', traits);
|
4223
|
+
} else {
|
4224
|
+
extend(traits, {
|
4225
|
+
app_id : this.options.appId,
|
4226
|
+
user_id : userId
|
4227
|
+
});
|
4228
|
+
window.Intercom('boot', traits);
|
4229
|
+
}
|
4230
|
+
|
4231
|
+
// Set the booted state, so that we know to call 'update' next time.
|
4232
|
+
this.booted = true;
|
4233
|
+
},
|
4234
|
+
|
4235
|
+
// Intercom doesn't have a separate `group` method, but they take a
|
4236
|
+
// `companies` trait for the user.
|
4237
|
+
group : function (groupId, properties, options) {
|
4238
|
+
properties.id = groupId;
|
4239
|
+
window.Intercom('update', { company : properties });
|
4240
|
+
}
|
4241
|
+
|
4242
|
+
});
|
4243
|
+
|
4244
|
+
});
|
4245
|
+
require.register("analytics/src/providers/keen-io.js", function(exports, require, module){
|
4246
|
+
// https://keen.io/docs/
|
4247
|
+
|
4248
|
+
var Provider = require('../provider')
|
4249
|
+
, load = require('load-script');
|
4250
|
+
|
4251
|
+
|
4252
|
+
module.exports = Provider.extend({
|
4253
|
+
|
4254
|
+
name : 'Keen IO',
|
4255
|
+
|
4256
|
+
defaults : {
|
4257
|
+
// The Project ID is **required**.
|
4258
|
+
projectId : null,
|
4259
|
+
// The Write Key is **required** to send events.
|
4260
|
+
writeKey : null,
|
4261
|
+
// The Read Key is optional, only if you want to "do analysis".
|
4262
|
+
readKey : null,
|
4263
|
+
// Whether or not to pass pageviews on to Keen IO.
|
4264
|
+
pageview : true,
|
4265
|
+
// Whether or not to track an initial pageview on `initialize`.
|
4266
|
+
initialPageview : true
|
4267
|
+
},
|
4268
|
+
|
4269
|
+
initialize : function (options, ready) {
|
4270
|
+
window.Keen = window.Keen||{configure:function(e){this._cf=e},addEvent:function(e,t,n,i){this._eq=this._eq||[],this._eq.push([e,t,n,i])},setGlobalProperties:function(e){this._gp=e},onChartsReady:function(e){this._ocrq=this._ocrq||[],this._ocrq.push(e)}};
|
4271
|
+
window.Keen.configure({
|
4272
|
+
projectId : options.projectId,
|
4273
|
+
writeKey : options.writeKey,
|
4274
|
+
readKey : options.readKey
|
4275
|
+
});
|
4276
|
+
|
4277
|
+
load('//dc8na2hxrj29i.cloudfront.net/code/keen-2.1.0-min.js');
|
4278
|
+
|
4279
|
+
if (options.initialPageview) this.pageview();
|
4280
|
+
|
4281
|
+
// Keen IO defines all their functions in the snippet, so they're ready.
|
4282
|
+
ready();
|
4283
|
+
},
|
4284
|
+
|
4285
|
+
identify : function (userId, traits) {
|
4286
|
+
// Use Keen IO global properties to include `userId` and `traits` on
|
4287
|
+
// every event sent to Keen IO.
|
4288
|
+
var globalUserProps = {};
|
4289
|
+
if (userId) globalUserProps.userId = userId;
|
4290
|
+
if (traits) globalUserProps.traits = traits;
|
4291
|
+
if (userId || traits) {
|
4292
|
+
window.Keen.setGlobalProperties(function(eventCollection) {
|
4293
|
+
return { user: globalUserProps };
|
4294
|
+
});
|
4295
|
+
}
|
4296
|
+
},
|
4297
|
+
|
4298
|
+
track : function (event, properties) {
|
4299
|
+
window.Keen.addEvent(event, properties);
|
4300
|
+
},
|
4301
|
+
|
4302
|
+
pageview : function (url) {
|
4303
|
+
if (!this.options.pageview) return;
|
4304
|
+
|
4305
|
+
var properties = {
|
4306
|
+
url : url || document.location.href,
|
4307
|
+
name : document.title
|
4308
|
+
};
|
4309
|
+
|
4310
|
+
this.track('Loaded a Page', properties);
|
4311
|
+
}
|
4312
|
+
|
4313
|
+
});
|
4314
|
+
});
|
4315
|
+
require.register("analytics/src/providers/kissmetrics.js", function(exports, require, module){
|
4316
|
+
// http://support.kissmetrics.com/apis/javascript
|
4317
|
+
|
4318
|
+
var Provider = require('../provider')
|
4319
|
+
, alias = require('alias')
|
4320
|
+
, load = require('load-script');
|
4321
|
+
|
4322
|
+
|
4323
|
+
module.exports = Provider.extend({
|
4324
|
+
|
4325
|
+
name : 'KISSmetrics',
|
4326
|
+
|
4327
|
+
key : 'apiKey',
|
4328
|
+
|
4329
|
+
defaults : {
|
4330
|
+
apiKey : null
|
4331
|
+
},
|
4332
|
+
|
4333
|
+
initialize : function (options, ready) {
|
4334
|
+
window._kmq = window._kmq || [];
|
4335
|
+
load('//i.kissmetrics.com/i.js');
|
4336
|
+
load('//doug1izaerwt3.cloudfront.net/' + options.apiKey + '.1.js');
|
4337
|
+
|
4338
|
+
// KISSmetrics creates a queue, so it's ready immediately.
|
4339
|
+
ready();
|
4340
|
+
},
|
4341
|
+
|
4342
|
+
// KISSmetrics uses two separate methods: `identify` for storing the
|
4343
|
+
// `userId`, and `set` for storing `traits`.
|
4344
|
+
identify : function (userId, traits) {
|
4345
|
+
if (userId) window._kmq.push(['identify', userId]);
|
4346
|
+
if (traits) window._kmq.push(['set', traits]);
|
4347
|
+
},
|
4348
|
+
|
4349
|
+
track : function (event, properties) {
|
4350
|
+
// KISSmetrics handles revenue with the `'Billing Amount'` property by
|
4351
|
+
// default, although it's changeable in the interface.
|
4352
|
+
if (properties) {
|
4353
|
+
alias(properties, {
|
4354
|
+
'revenue' : 'Billing Amount'
|
4355
|
+
});
|
4356
|
+
}
|
4357
|
+
|
4358
|
+
window._kmq.push(['record', event, properties]);
|
4359
|
+
},
|
4360
|
+
|
4361
|
+
// Although undocumented, KISSmetrics actually supports not passing a second
|
4362
|
+
// ID, in which case it uses the currenty identified user's ID.
|
4363
|
+
alias : function (newId, originalId) {
|
4364
|
+
window._kmq.push(['alias', newId, originalId]);
|
4365
|
+
}
|
4366
|
+
|
4367
|
+
});
|
4368
|
+
});
|
4369
|
+
require.register("analytics/src/providers/klaviyo.js", function(exports, require, module){
|
4370
|
+
// https://www.klaviyo.com/docs
|
4371
|
+
|
4372
|
+
var Provider = require('../provider')
|
4373
|
+
, load = require('load-script');
|
4374
|
+
|
4375
|
+
|
4376
|
+
module.exports = Provider.extend({
|
4377
|
+
|
4378
|
+
name : 'Klaviyo',
|
4379
|
+
|
4380
|
+
key : 'apiKey',
|
4381
|
+
|
4382
|
+
defaults : {
|
4383
|
+
apiKey : null
|
4384
|
+
},
|
4385
|
+
|
4386
|
+
initialize : function (options, ready) {
|
4387
|
+
window._learnq = window._learnq || [];
|
4388
|
+
window._learnq.push(['account', options.apiKey]);
|
4389
|
+
load('//a.klaviyo.com/media/js/learnmarklet.js');
|
4390
|
+
|
4391
|
+
// Klaviyo creats a queue, so it's ready immediately.
|
4392
|
+
ready();
|
4393
|
+
},
|
4394
|
+
|
4395
|
+
identify : function (userId, traits) {
|
4396
|
+
// Klaviyo requires a `userId` and takes the it on the traits object itself.
|
4397
|
+
if (!userId) return;
|
4398
|
+
traits.$id = userId;
|
4399
|
+
window._learnq.push(['identify', traits]);
|
4400
|
+
},
|
4401
|
+
|
4402
|
+
track : function (event, properties) {
|
4403
|
+
window._learnq.push(['track', event, properties]);
|
4404
|
+
}
|
4405
|
+
|
4406
|
+
});
|
4407
|
+
});
|
4408
|
+
require.register("analytics/src/providers/livechat.js", function(exports, require, module){
|
4409
|
+
// http://www.livechatinc.com/api/javascript-api
|
4410
|
+
|
4411
|
+
var Provider = require('../provider')
|
4412
|
+
, each = require('each')
|
4413
|
+
, load = require('load-script');
|
4414
|
+
|
4415
|
+
|
4416
|
+
module.exports = Provider.extend({
|
4417
|
+
|
4418
|
+
name : 'LiveChat',
|
4419
|
+
|
4420
|
+
key : 'license',
|
4421
|
+
|
4422
|
+
defaults : {
|
4423
|
+
license : null
|
4424
|
+
},
|
4425
|
+
|
4426
|
+
initialize : function (options, ready) {
|
4427
|
+
window.__lc = { license : options.license };
|
4428
|
+
load('//cdn.livechatinc.com/tracking.js', ready);
|
4429
|
+
},
|
4430
|
+
|
4431
|
+
// LiveChat isn't an analytics service, but we can use the `userId` and
|
4432
|
+
// `traits` to tag the user with their real name in the chat console.
|
4433
|
+
identify : function (userId, traits) {
|
4434
|
+
// In case the LiveChat library hasn't loaded yet.
|
4435
|
+
if (!window.LC_API) return;
|
4436
|
+
|
4437
|
+
// LiveChat takes them in an array format.
|
4438
|
+
var variables = [];
|
4439
|
+
|
4440
|
+
if (userId) variables.push({ name: 'User ID', value: userId });
|
4441
|
+
if (traits) {
|
4442
|
+
each(traits, function (key, value) {
|
4443
|
+
variables.push({
|
4444
|
+
name : key,
|
4445
|
+
value : value
|
4446
|
+
});
|
4447
|
+
});
|
4448
|
+
}
|
4449
|
+
|
4450
|
+
window.LC_API.set_custom_variables(variables);
|
4451
|
+
}
|
4452
|
+
|
4453
|
+
});
|
4454
|
+
});
|
4455
|
+
require.register("analytics/src/providers/lytics.js", function(exports, require, module){
|
4456
|
+
// Lytics
|
4457
|
+
// --------
|
4458
|
+
// [Documentation](http://developer.lytics.io/doc#jstag),
|
4459
|
+
|
4460
|
+
var Provider = require('../provider')
|
4461
|
+
, load = require('load-script');
|
4462
|
+
|
4463
|
+
|
4464
|
+
module.exports = Provider.extend({
|
4465
|
+
|
4466
|
+
name : 'Lytics',
|
4467
|
+
|
4468
|
+
key : 'cid',
|
4469
|
+
|
4470
|
+
defaults : {
|
4471
|
+
cid: null
|
4472
|
+
},
|
4473
|
+
|
4474
|
+
initialize : function (options, ready) {
|
4475
|
+
window.jstag = (function () {
|
4476
|
+
var t={_q:[],_c:{cid:options.cid,url:'//c.lytics.io'},ts:(new Date()).getTime()};
|
4477
|
+
t.send=function(){
|
4478
|
+
this._q.push(["ready","send",Array.prototype.slice.call(arguments)]);
|
4479
|
+
return this;
|
4480
|
+
};
|
4481
|
+
return t;
|
4482
|
+
})();
|
4483
|
+
|
4484
|
+
load('//c.lytics.io/static/io.min.js');
|
4485
|
+
|
4486
|
+
ready();
|
4487
|
+
},
|
4488
|
+
|
4489
|
+
identify: function (userId, traits) {
|
4490
|
+
traits._uid = userId;
|
4491
|
+
window.jstag.send(traits);
|
4492
|
+
},
|
4493
|
+
|
4494
|
+
track: function (event, properties) {
|
4495
|
+
properties._e = event;
|
4496
|
+
window.jstag.send(properties);
|
4497
|
+
},
|
4498
|
+
|
4499
|
+
pageview: function (url) {
|
4500
|
+
window.jstag.send();
|
4501
|
+
}
|
4502
|
+
|
4503
|
+
});
|
4504
|
+
});
|
4505
|
+
require.register("analytics/src/providers/mixpanel.js", function(exports, require, module){
|
4506
|
+
// https://mixpanel.com/docs/integration-libraries/javascript
|
4507
|
+
// https://mixpanel.com/docs/people-analytics/javascript
|
4508
|
+
// https://mixpanel.com/docs/integration-libraries/javascript-full-api
|
4509
|
+
|
4510
|
+
var Provider = require('../provider')
|
4511
|
+
, alias = require('alias')
|
4512
|
+
, isEmail = require('is-email')
|
4513
|
+
, load = require('load-script');
|
4514
|
+
|
4515
|
+
|
4516
|
+
module.exports = Provider.extend({
|
4517
|
+
|
4518
|
+
name : 'Mixpanel',
|
4519
|
+
|
4520
|
+
key : 'token',
|
4521
|
+
|
4522
|
+
defaults : {
|
4523
|
+
// Whether to call `mixpanel.nameTag` on `identify`.
|
4524
|
+
nameTag : true,
|
4525
|
+
// Whether to use Mixpanel's People API.
|
4526
|
+
people : false,
|
4527
|
+
// The Mixpanel API token for your account.
|
4528
|
+
token : null,
|
4529
|
+
// Whether to track pageviews to Mixpanel.
|
4530
|
+
pageview : false,
|
4531
|
+
// Whether to track an initial pageview on initialize.
|
4532
|
+
initialPageview : false,
|
4533
|
+
// A custom cookie name to use
|
4534
|
+
cookieName : null
|
4535
|
+
},
|
4536
|
+
|
4537
|
+
initialize : function (options, ready) {
|
4538
|
+
(function (c, a) {
|
4539
|
+
window.mixpanel = a;
|
4540
|
+
var b, d, h, e;
|
4541
|
+
a._i = [];
|
4542
|
+
a.init = function (b, c, f) {
|
4543
|
+
function d(a, b) {
|
4544
|
+
var c = b.split('.');
|
4545
|
+
2 == c.length && (a = a[c[0]], b = c[1]);
|
4546
|
+
a[b] = function () {
|
4547
|
+
a.push([b].concat(Array.prototype.slice.call(arguments, 0)));
|
4548
|
+
};
|
4549
|
+
}
|
4550
|
+
var g = a;
|
4551
|
+
'undefined' !== typeof f ? g = a[f] = [] : f = 'mixpanel';
|
4552
|
+
g.people = g.people || [];
|
4553
|
+
h = ['disable', 'track', 'track_pageview', 'track_links', 'track_forms', 'register', 'register_once', 'unregister', 'identify', 'alias', 'name_tag', 'set_config', 'people.set', 'people.increment', 'people.track_charge', 'people.append'];
|
4554
|
+
for (e = 0; e < h.length; e++) d(g, h[e]);
|
4555
|
+
a._i.push([b, c, f]);
|
4556
|
+
};
|
4557
|
+
a.__SV = 1.2;
|
4558
|
+
// Modification to the snippet: call ready whenever the library has
|
4559
|
+
// fully loaded.
|
4560
|
+
load('//cdn.mxpnl.com/libs/mixpanel-2.2.min.js', ready);
|
4561
|
+
})(document, window.mixpanel || []);
|
4562
|
+
|
4563
|
+
// Mixpanel only accepts snake_case options
|
4564
|
+
options.cookie_name = options.cookieName;
|
4565
|
+
|
4566
|
+
// Pass options directly to `init` as the second argument.
|
4567
|
+
window.mixpanel.init(options.token, options);
|
4568
|
+
|
4569
|
+
if (options.initialPageview) this.pageview();
|
4570
|
+
},
|
4571
|
+
|
4572
|
+
identify : function (userId, traits) {
|
4573
|
+
// Alias the traits' keys with dollar signs for Mixpanel's API.
|
4574
|
+
alias(traits, {
|
4575
|
+
'created' : '$created',
|
4576
|
+
'email' : '$email',
|
4577
|
+
'firstName' : '$first_name',
|
4578
|
+
'lastName' : '$last_name',
|
4579
|
+
'lastSeen' : '$last_seen',
|
4580
|
+
'name' : '$name',
|
4581
|
+
'username' : '$username',
|
4582
|
+
'phone' : '$phone'
|
4583
|
+
});
|
4584
|
+
|
4585
|
+
// Finally, call all of the identify equivalents. Verify certain calls
|
4586
|
+
// against options to make sure they're enabled.
|
4587
|
+
if (userId) {
|
4588
|
+
window.mixpanel.identify(userId);
|
4589
|
+
if (this.options.nameTag) window.mixpanel.name_tag(traits && traits.$email || userId);
|
4590
|
+
}
|
4591
|
+
if (traits) {
|
4592
|
+
window.mixpanel.register(traits);
|
4593
|
+
if (this.options.people) window.mixpanel.people.set(traits);
|
4594
|
+
}
|
4595
|
+
},
|
4596
|
+
|
4597
|
+
track : function (event, properties) {
|
4598
|
+
window.mixpanel.track(event, properties);
|
4599
|
+
|
4600
|
+
// Mixpanel handles revenue with a `transaction` call in their People
|
4601
|
+
// feature. So if we're using people, record a transcation.
|
4602
|
+
if (properties && properties.revenue && this.options.people) {
|
4603
|
+
window.mixpanel.people.track_charge(properties.revenue);
|
4604
|
+
}
|
4605
|
+
},
|
4606
|
+
|
4607
|
+
// Mixpanel doesn't actually track the pageviews, but they do show up in the
|
4608
|
+
// Mixpanel stream.
|
4609
|
+
pageview : function (url) {
|
4610
|
+
window.mixpanel.track_pageview(url);
|
4611
|
+
|
4612
|
+
// If they don't want pageviews tracked, leave now.
|
4613
|
+
if (!this.options.pageview) return;
|
4614
|
+
|
4615
|
+
var properties = {
|
4616
|
+
url : url || document.location.href,
|
4617
|
+
name : document.title
|
4618
|
+
};
|
4619
|
+
|
4620
|
+
this.track('Loaded a Page', properties);
|
4621
|
+
},
|
4622
|
+
|
4623
|
+
// Although undocumented, Mixpanel actually supports the `originalId`. It
|
4624
|
+
// just usually defaults to the current user's `distinct_id`.
|
4625
|
+
alias : function (newId, originalId) {
|
4626
|
+
|
4627
|
+
if(window.mixpanel.get_distinct_id &&
|
4628
|
+
window.mixpanel.get_distinct_id() === newId) return;
|
4629
|
+
|
4630
|
+
// HACK: internal mixpanel API to ensure we don't overwrite.
|
4631
|
+
if(window.mixpanel.get_property &&
|
4632
|
+
window.mixpanel.get_property('$people_distinct_id') === newId) return;
|
4633
|
+
|
4634
|
+
window.mixpanel.alias(newId, originalId);
|
4635
|
+
}
|
4636
|
+
|
4637
|
+
});
|
4638
|
+
});
|
4639
|
+
require.register("analytics/src/providers/olark.js", function(exports, require, module){
|
4640
|
+
// http://www.olark.com/documentation
|
4641
|
+
|
4642
|
+
var Provider = require('../provider')
|
4643
|
+
, isEmail = require('is-email');
|
4644
|
+
|
4645
|
+
|
4646
|
+
module.exports = Provider.extend({
|
4647
|
+
|
4648
|
+
name : 'Olark',
|
4649
|
+
|
4650
|
+
key : 'siteId',
|
4651
|
+
|
4652
|
+
chatting : false,
|
4653
|
+
|
4654
|
+
defaults : {
|
4655
|
+
siteId : null,
|
4656
|
+
// Whether to use the user's name or email in the Olark chat console.
|
4657
|
+
identify : true,
|
4658
|
+
// Whether to log pageviews to the Olark chat console.
|
4659
|
+
track : false,
|
4660
|
+
// Whether to log pageviews to the Olark chat console.
|
4661
|
+
pageview : true
|
4662
|
+
},
|
4663
|
+
|
4664
|
+
initialize : function (options, ready) {
|
4665
|
+
window.olark||(function(c){var f=window,d=document,l=f.location.protocol=="https:"?"https:":"http:",z=c.name,r="load";var nt=function(){f[z]=function(){(a.s=a.s||[]).push(arguments)};var a=f[z]._={},q=c.methods.length;while(q--){(function(n){f[z][n]=function(){f[z]("call",n,arguments)}})(c.methods[q])}a.l=c.loader;a.i=nt;a.p={0:+new Date};a.P=function(u){a.p[u]=new Date-a.p[0]};function s(){a.P(r);f[z](r)}f.addEventListener?f.addEventListener(r,s,false):f.attachEvent("on"+r,s);var ld=function(){function p(hd){hd="head";return["<",hd,"></",hd,"><",i,' onl' + 'oad="var d=',g,";d.getElementsByTagName('head')[0].",j,"(d.",h,"('script')).",k,"='",l,"//",a.l,"'",'"',"></",i,">"].join("")}var i="body",m=d[i];if(!m){return setTimeout(ld,100)}a.P(1);var j="appendChild",h="createElement",k="src",n=d[h]("div"),v=n[j](d[h](z)),b=d[h]("iframe"),g="document",e="domain",o;n.style.display="none";m.insertBefore(n,m.firstChild).id=z;b.frameBorder="0";b.id=z+"-loader";if(/MSIE[ ]+6/.test(navigator.userAgent)){b.src="javascript:false"}b.allowTransparency="true";v[j](b);try{b.contentWindow[g].open()}catch(w){c[e]=d[e];o="javascript:var d="+g+".open();d.domain='"+d.domain+"';";b[k]=o+"void(0);"}try{var t=b.contentWindow[g];t.write(p());t.close()}catch(x){b[k]=o+'d.write("'+p().replace(/"/g,String.fromCharCode(92)+'"')+'");d.close();'}a.P(2)};ld()};nt()})({loader: "static.olark.com/jsclient/loader0.js",name:"olark",methods:["configure","extend","declare","identify"]});
|
4666
|
+
window.olark.identify(options.siteId);
|
4667
|
+
|
4668
|
+
// Set up event handlers for chat box open and close so that
|
4669
|
+
// we know whether a conversation is active. If it is active,
|
4670
|
+
// then we'll send track and pageview information.
|
4671
|
+
var self = this;
|
4672
|
+
window.olark('api.box.onExpand', function () { self.chatting = true; });
|
4673
|
+
window.olark('api.box.onShrink', function () { self.chatting = false; });
|
4674
|
+
|
4675
|
+
// Olark creates it's method in the snippet, so it's ready immediately.
|
4676
|
+
ready();
|
4677
|
+
},
|
4678
|
+
|
4679
|
+
// Update traits about the user in Olark to make the operator's life easier.
|
4680
|
+
identify : function (userId, traits) {
|
4681
|
+
if (!this.options.identify) return;
|
4682
|
+
|
4683
|
+
var email = traits.email
|
4684
|
+
, name = traits.name || traits.firstName
|
4685
|
+
, phone = traits.phone
|
4686
|
+
, nickname = name || email || userId;
|
4687
|
+
|
4688
|
+
// If we have a name and an email, add the email too to be more helpful.
|
4689
|
+
if (name && email) nickname += ' ('+email+')';
|
4690
|
+
|
4691
|
+
// Call all of Olark's settings APIs.
|
4692
|
+
window.olark('api.visitor.updateCustomFields', traits);
|
4693
|
+
if (email) window.olark('api.visitor.updateEmailAddress', { emailAddress : email });
|
4694
|
+
if (name) window.olark('api.visitor.updateFullName', { fullName : name });
|
4695
|
+
if (phone) window.olark('api.visitor.updatePhoneNumber', { phoneNumber : phone });
|
4696
|
+
if (nickname) window.olark('api.chat.updateVisitorNickname', { snippet : nickname });
|
4697
|
+
},
|
4698
|
+
|
4699
|
+
// Log events the user triggers to the chat console, if you so desire it.
|
4700
|
+
track : function (event, properties) {
|
4701
|
+
if (!this.options.track || !this.chatting) return;
|
4702
|
+
|
4703
|
+
// To stay consistent with olark's default messages, it's all lowercase.
|
4704
|
+
window.olark('api.chat.sendNotificationToOperator', {
|
4705
|
+
body : 'visitor triggered "'+event+'"'
|
4706
|
+
});
|
4707
|
+
},
|
4708
|
+
|
4709
|
+
// Mimic the functionality Olark has for normal pageviews with pseudo-
|
4710
|
+
// pageviews, telling the operator when a visitor changes pages.
|
4711
|
+
pageview : function (url) {
|
4712
|
+
if (!this.options.pageview || !this.chatting) return;
|
4713
|
+
|
4714
|
+
// To stay consistent with olark's default messages, it's all lowercase.
|
4715
|
+
window.olark('api.chat.sendNotificationToOperator', {
|
4716
|
+
body : 'looking at ' + window.location.href
|
4717
|
+
});
|
4718
|
+
}
|
4719
|
+
|
4720
|
+
});
|
4721
|
+
});
|
4722
|
+
require.register("analytics/src/providers/optimizely.js", function(exports, require, module){
|
4723
|
+
// https://www.optimizely.com/docs/api
|
4724
|
+
|
4725
|
+
var each = require('each')
|
4726
|
+
, nextTick = require('next-tick')
|
4727
|
+
, Provider = require('../provider');
|
4728
|
+
|
4729
|
+
|
4730
|
+
module.exports = Provider.extend({
|
4731
|
+
|
4732
|
+
name : 'Optimizely',
|
4733
|
+
|
4734
|
+
defaults : {
|
4735
|
+
// Whether to replay variations into other enabled integrations as traits.
|
4736
|
+
variations : true
|
4737
|
+
},
|
4738
|
+
|
4739
|
+
initialize : function (options, ready, analytics) {
|
4740
|
+
// Create the `optimizely` object in case it doesn't exist already.
|
4741
|
+
// https://www.optimizely.com/docs/api#function-calls
|
4742
|
+
window.optimizely = window.optimizely || [];
|
4743
|
+
|
4744
|
+
// If the `variations` option is true, replay our variations on the next
|
4745
|
+
// tick to wait for the entire library to be ready for replays.
|
4746
|
+
if (options.variations) {
|
4747
|
+
var self = this;
|
4748
|
+
nextTick(function () { self.replay(); });
|
4749
|
+
}
|
4750
|
+
|
4751
|
+
// Optimizely should be on the page already, so it's always ready.
|
4752
|
+
ready();
|
4753
|
+
},
|
4754
|
+
|
4755
|
+
track : function (event, properties) {
|
4756
|
+
// Optimizely takes revenue as cents, not dollars.
|
4757
|
+
if (properties && properties.revenue) properties.revenue = properties.revenue * 100;
|
4758
|
+
|
4759
|
+
window.optimizely.push(['trackEvent', event, properties]);
|
4760
|
+
},
|
4761
|
+
|
4762
|
+
replay : function () {
|
4763
|
+
// Make sure we have access to Optimizely's `data` dictionary.
|
4764
|
+
var data = window.optimizely.data;
|
4765
|
+
if (!data) return;
|
4766
|
+
|
4767
|
+
// Grab a few pieces of data we'll need for replaying.
|
4768
|
+
var experiments = data.experiments
|
4769
|
+
, variationNamesMap = data.state.variationNamesMap;
|
4770
|
+
|
4771
|
+
// Create our traits object to add variations to.
|
4772
|
+
var traits = {};
|
4773
|
+
|
4774
|
+
// Loop through all the experiement the user has been assigned a variation
|
4775
|
+
// for and add them to our traits.
|
4776
|
+
each(variationNamesMap, function (experimentId, variation) {
|
4777
|
+
traits['Experiment: ' + experiments[experimentId].name] = variation;
|
4778
|
+
});
|
4779
|
+
|
4780
|
+
this.analytics.identify(traits);
|
4781
|
+
}
|
4782
|
+
|
4783
|
+
});
|
4784
|
+
});
|
4785
|
+
require.register("analytics/src/providers/perfect-audience.js", function(exports, require, module){
|
4786
|
+
// https://www.perfectaudience.com/docs#javascript_api_autoopen
|
4787
|
+
|
4788
|
+
var Provider = require('../provider')
|
4789
|
+
, load = require('load-script');
|
4790
|
+
|
4791
|
+
|
4792
|
+
module.exports = Provider.extend({
|
4793
|
+
|
4794
|
+
name : 'Perfect Audience',
|
4795
|
+
|
4796
|
+
key : 'siteId',
|
4797
|
+
|
4798
|
+
defaults : {
|
4799
|
+
siteId : null
|
4800
|
+
},
|
4801
|
+
|
4802
|
+
initialize : function (options, ready) {
|
4803
|
+
window._pa || (window._pa = {});
|
4804
|
+
load('//tag.perfectaudience.com/serve/' + options.siteId + '.js', ready);
|
4805
|
+
},
|
4806
|
+
|
4807
|
+
track : function (event, properties) {
|
4808
|
+
window._pa.track(event, properties);
|
4809
|
+
}
|
4810
|
+
|
4811
|
+
});
|
4812
|
+
});
|
4813
|
+
require.register("analytics/src/providers/pingdom.js", function(exports, require, module){
|
4814
|
+
var date = require('load-date')
|
4815
|
+
, Provider = require('../provider')
|
4816
|
+
, load = require('load-script');
|
4817
|
+
|
4818
|
+
|
4819
|
+
module.exports = Provider.extend({
|
4820
|
+
|
4821
|
+
name : 'Pingdom',
|
4822
|
+
|
4823
|
+
key : 'id',
|
4824
|
+
|
4825
|
+
defaults : {
|
4826
|
+
id : null
|
4827
|
+
},
|
4828
|
+
|
4829
|
+
initialize : function (options, ready) {
|
4830
|
+
|
4831
|
+
window._prum = [
|
4832
|
+
['id', options.id],
|
4833
|
+
['mark', 'firstbyte', date.getTime()]
|
4834
|
+
];
|
4835
|
+
|
4836
|
+
// We've replaced the original snippet loader with our own load method.
|
4837
|
+
load('//rum-static.pingdom.net/prum.min.js', ready);
|
4838
|
+
}
|
4839
|
+
|
4840
|
+
});
|
4841
|
+
});
|
4842
|
+
require.register("analytics/src/providers/preact.js", function(exports, require, module){
|
4843
|
+
// http://www.preact.io/api/javascript
|
4844
|
+
|
4845
|
+
var Provider = require('../provider')
|
4846
|
+
, isEmail = require('is-email')
|
4847
|
+
, load = require('load-script');
|
4848
|
+
|
4849
|
+
module.exports = Provider.extend({
|
4850
|
+
|
4851
|
+
name : 'Preact',
|
4852
|
+
|
4853
|
+
key : 'projectCode',
|
4854
|
+
|
4855
|
+
defaults : {
|
4856
|
+
projectCode : null
|
4857
|
+
},
|
4858
|
+
|
4859
|
+
initialize : function (options, ready) {
|
4860
|
+
var _lnq = window._lnq = window._lnq || [];
|
4861
|
+
_lnq.push(["_setCode", options.projectCode]);
|
4862
|
+
|
4863
|
+
load('//d2bbvl6dq48fa6.cloudfront.net/js/ln-2.4.min.js');
|
4864
|
+
ready();
|
4865
|
+
},
|
4866
|
+
|
4867
|
+
identify : function (userId, traits) {
|
4868
|
+
// Don't do anything if we just have traits. Preact requires a `userId`.
|
4869
|
+
if (!userId) return;
|
4870
|
+
|
4871
|
+
// Swap the `created` trait to the `created_at` that Preact needs
|
4872
|
+
// and convert it from milliseconds to seconds.
|
4873
|
+
if (traits.created) {
|
4874
|
+
traits.created_at = Math.floor(traits.created/1000);
|
4875
|
+
delete traits.created;
|
4876
|
+
}
|
4877
|
+
|
4878
|
+
window._lnq.push(['_setPersonData', {
|
4879
|
+
name : traits.name,
|
4880
|
+
email : traits.email,
|
4881
|
+
uid : userId,
|
4882
|
+
properties : traits
|
4883
|
+
}]);
|
4884
|
+
},
|
4885
|
+
|
4886
|
+
group : function (groupId, properties) {
|
4887
|
+
if (!groupId) return;
|
4888
|
+
properties.id = groupId;
|
4889
|
+
window._lnq.push(['_setAccount', properties]);
|
4890
|
+
},
|
4891
|
+
|
4892
|
+
track : function (event, properties) {
|
4893
|
+
properties || (properties = {});
|
4894
|
+
|
4895
|
+
// Preact takes a few special properties, and the rest in `extras`. So first
|
4896
|
+
// convert and remove the special ones from `properties`.
|
4897
|
+
var special = { name : event };
|
4898
|
+
|
4899
|
+
// They take `revenue` in cents.
|
4900
|
+
if (properties.revenue) {
|
4901
|
+
special.revenue = properties.revenue * 100;
|
4902
|
+
delete properties.revenue;
|
4903
|
+
}
|
4904
|
+
|
4905
|
+
if (properties.note) {
|
4906
|
+
special.note = properties.note;
|
4907
|
+
delete properties.note;
|
4908
|
+
}
|
4909
|
+
|
4910
|
+
window._lnq.push(['_logEvent', special, properties]);
|
4911
|
+
}
|
4912
|
+
|
4913
|
+
});
|
4914
|
+
});
|
4915
|
+
require.register("analytics/src/providers/qualaroo.js", function(exports, require, module){
|
4916
|
+
// http://help.qualaroo.com/customer/portal/articles/731085-identify-survey-nudge-takers
|
4917
|
+
// http://help.qualaroo.com/customer/portal/articles/731091-set-additional-user-properties
|
4918
|
+
|
4919
|
+
var Provider = require('../provider')
|
4920
|
+
, isEmail = require('is-email')
|
4921
|
+
, load = require('load-script');
|
4922
|
+
|
4923
|
+
|
4924
|
+
module.exports = Provider.extend({
|
4925
|
+
|
4926
|
+
name : 'Qualaroo',
|
4927
|
+
|
4928
|
+
defaults : {
|
4929
|
+
// Qualaroo has two required options.
|
4930
|
+
customerId : null,
|
4931
|
+
siteToken : null,
|
4932
|
+
// Whether to record traits when a user triggers an event. This can be
|
4933
|
+
// useful for sending targetted questionnaries.
|
4934
|
+
track : false
|
4935
|
+
},
|
4936
|
+
|
4937
|
+
// Qualaroo's script has two options in its URL.
|
4938
|
+
initialize : function (options, ready) {
|
4939
|
+
window._kiq = window._kiq || [];
|
4940
|
+
load('//s3.amazonaws.com/ki.js/' + options.customerId + '/' + options.siteToken + '.js');
|
4941
|
+
|
4942
|
+
// Qualaroo creates a queue, so it's ready immediately.
|
4943
|
+
ready();
|
4944
|
+
},
|
4945
|
+
|
4946
|
+
// Qualaroo uses two separate methods: `identify` for storing the `userId`,
|
4947
|
+
// and `set` for storing `traits`.
|
4948
|
+
identify : function (userId, traits) {
|
4949
|
+
var identity = traits.email || userId;
|
4950
|
+
if (identity) window._kiq.push(['identify', identity]);
|
4951
|
+
if (traits) window._kiq.push(['set', traits]);
|
4952
|
+
},
|
4953
|
+
|
4954
|
+
// Qualaroo doesn't have `track` method yet, but to allow the users to do
|
4955
|
+
// targetted questionnaires we can set name-value pairs on the user properties
|
4956
|
+
// that apply to the current visit.
|
4957
|
+
track : function (event, properties) {
|
4958
|
+
if (!this.options.track) return;
|
4959
|
+
|
4960
|
+
// Create a name-value pair that will be pretty unique. For an event like
|
4961
|
+
// 'Loaded a Page' this will make it 'Triggered: Loaded a Page'.
|
4962
|
+
var traits = {};
|
4963
|
+
traits['Triggered: ' + event] = true;
|
4964
|
+
|
4965
|
+
// Fire a normal identify, with traits only.
|
4966
|
+
this.identify(null, traits);
|
4967
|
+
}
|
4968
|
+
|
4969
|
+
});
|
4970
|
+
});
|
4971
|
+
require.register("analytics/src/providers/quantcast.js", function(exports, require, module){
|
4972
|
+
// https://www.quantcast.com/learning-center/guides/using-the-quantcast-asynchronous-tag/
|
4973
|
+
|
4974
|
+
var Provider = require('../provider')
|
4975
|
+
, load = require('load-script');
|
4976
|
+
|
4977
|
+
|
4978
|
+
module.exports = Provider.extend({
|
4979
|
+
|
4980
|
+
name : 'Quantcast',
|
4981
|
+
|
4982
|
+
key : 'pCode',
|
4983
|
+
|
4984
|
+
defaults : {
|
4985
|
+
pCode : null
|
4986
|
+
},
|
4987
|
+
|
4988
|
+
initialize : function (options, ready) {
|
4989
|
+
window._qevents = window._qevents || [];
|
4990
|
+
window._qevents.push({ qacct: options.pCode });
|
4991
|
+
load({
|
4992
|
+
http : 'http://edge.quantserve.com/quant.js',
|
4993
|
+
https : 'https://secure.quantserve.com/quant.js'
|
4994
|
+
}, ready);
|
4995
|
+
}
|
4996
|
+
|
4997
|
+
});
|
4998
|
+
});
|
4999
|
+
require.register("analytics/src/providers/sentry.js", function(exports, require, module){
|
5000
|
+
// http://raven-js.readthedocs.org/en/latest/config/index.html
|
5001
|
+
|
5002
|
+
var Provider = require('../provider')
|
5003
|
+
, load = require('load-script');
|
5004
|
+
|
5005
|
+
|
5006
|
+
module.exports = Provider.extend({
|
5007
|
+
|
5008
|
+
name : 'Sentry',
|
5009
|
+
|
5010
|
+
key : 'config',
|
5011
|
+
|
5012
|
+
defaults : {
|
5013
|
+
config : null
|
5014
|
+
},
|
5015
|
+
|
5016
|
+
initialize : function (options, ready) {
|
5017
|
+
load('//d3nslu0hdya83q.cloudfront.net/dist/1.0/raven.min.js', function () {
|
5018
|
+
// For now, Raven basically requires `install` to be called.
|
5019
|
+
// https://github.com/getsentry/raven-js/blob/master/src/raven.js#L87
|
5020
|
+
window.Raven.config(options.config).install();
|
5021
|
+
ready();
|
5022
|
+
});
|
5023
|
+
},
|
5024
|
+
|
5025
|
+
identify : function (userId, traits) {
|
5026
|
+
traits.id = userId;
|
5027
|
+
window.Raven.setUser(traits);
|
5028
|
+
},
|
5029
|
+
|
5030
|
+
// Raven will automatically use `captureMessage` if the error is a string.
|
5031
|
+
log : function (error, properties) {
|
5032
|
+
window.Raven.captureException(error, properties);
|
5033
|
+
}
|
5034
|
+
|
5035
|
+
});
|
5036
|
+
});
|
5037
|
+
require.register("analytics/src/providers/snapengage.js", function(exports, require, module){
|
5038
|
+
// http://help.snapengage.com/installation-guide-getting-started-in-a-snap/
|
5039
|
+
|
5040
|
+
var Provider = require('../provider')
|
5041
|
+
, isEmail = require('is-email')
|
5042
|
+
, load = require('load-script');
|
5043
|
+
|
5044
|
+
|
5045
|
+
module.exports = Provider.extend({
|
5046
|
+
|
5047
|
+
name : 'SnapEngage',
|
5048
|
+
|
5049
|
+
key : 'apiKey',
|
5050
|
+
|
5051
|
+
defaults : {
|
5052
|
+
apiKey : null
|
5053
|
+
},
|
5054
|
+
|
5055
|
+
initialize : function (options, ready) {
|
5056
|
+
load('//commondatastorage.googleapis.com/code.snapengage.com/js/' + options.apiKey + '.js', ready);
|
5057
|
+
},
|
5058
|
+
|
5059
|
+
// Set the email in the chat window if we have it.
|
5060
|
+
identify : function (userId, traits, options) {
|
5061
|
+
if (!traits.email) return;
|
5062
|
+
window.SnapABug.setUserEmail(traits.email);
|
5063
|
+
}
|
5064
|
+
|
5065
|
+
});
|
5066
|
+
});
|
5067
|
+
require.register("analytics/src/providers/usercycle.js", function(exports, require, module){
|
5068
|
+
// http://docs.usercycle.com/javascript_api
|
5069
|
+
|
5070
|
+
var Provider = require('../provider')
|
5071
|
+
, load = require('load-script')
|
5072
|
+
, user = require('../user');
|
5073
|
+
|
5074
|
+
|
5075
|
+
module.exports = Provider.extend({
|
5076
|
+
|
5077
|
+
name : 'USERcycle',
|
5078
|
+
|
5079
|
+
key : 'key',
|
5080
|
+
|
5081
|
+
defaults : {
|
5082
|
+
key : null
|
5083
|
+
},
|
5084
|
+
|
5085
|
+
initialize : function (options, ready) {
|
5086
|
+
window._uc = window._uc || [];
|
5087
|
+
window._uc.push(['_key', options.key]);
|
5088
|
+
load('//api.usercycle.com/javascripts/track.js');
|
5089
|
+
|
5090
|
+
// USERcycle makes a queue, so it's ready immediately.
|
5091
|
+
ready();
|
5092
|
+
},
|
5093
|
+
|
5094
|
+
identify : function (userId, traits) {
|
5095
|
+
if (userId) window._uc.push(['uid', userId]);
|
5096
|
+
|
5097
|
+
// USERcycle has a special "hidden" event that is used just for retention measurement.
|
5098
|
+
// Lukas suggested on 6/4/2013 that we send traits on that event, since they use the
|
5099
|
+
// the latest value of every event property as a "trait"
|
5100
|
+
window._uc.push(['action', 'came_back', traits]);
|
5101
|
+
},
|
5102
|
+
|
5103
|
+
track : function (event, properties) {
|
5104
|
+
window._uc.push(['action', event, properties]);
|
5105
|
+
}
|
5106
|
+
|
5107
|
+
});
|
5108
|
+
});
|
5109
|
+
require.register("analytics/src/providers/userfox.js", function(exports, require, module){
|
5110
|
+
// https://www.userfox.com/docs/
|
5111
|
+
|
5112
|
+
var Provider = require('../provider')
|
5113
|
+
, extend = require('extend')
|
5114
|
+
, load = require('load-script')
|
5115
|
+
, isEmail = require('is-email');
|
5116
|
+
|
5117
|
+
|
5118
|
+
module.exports = Provider.extend({
|
5119
|
+
|
5120
|
+
name : 'userfox',
|
5121
|
+
|
5122
|
+
key : 'clientId',
|
5123
|
+
|
5124
|
+
defaults : {
|
5125
|
+
// userfox's required key.
|
5126
|
+
clientId : null
|
5127
|
+
},
|
5128
|
+
|
5129
|
+
initialize : function (options, ready) {
|
5130
|
+
window._ufq = window._ufq || [];
|
5131
|
+
load('//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js');
|
5132
|
+
|
5133
|
+
// userfox creates its own queue, so we're ready right away.
|
5134
|
+
ready();
|
5135
|
+
},
|
5136
|
+
|
5137
|
+
identify : function (userId, traits) {
|
5138
|
+
if (!traits.email) return;
|
5139
|
+
|
5140
|
+
// Initialize the library with the email now that we have it.
|
5141
|
+
window._ufq.push(['init', {
|
5142
|
+
clientId : this.options.clientId,
|
5143
|
+
email : traits.email
|
5144
|
+
}]);
|
5145
|
+
|
5146
|
+
// Record traits to "track" if we have the required signup date `created`.
|
5147
|
+
// userfox takes `signup_date` as a string of seconds since the epoch.
|
5148
|
+
if (traits.created) {
|
5149
|
+
traits.signup_date = (traits.created.getTime() / 1000).toString();
|
5150
|
+
delete traits.created;
|
5151
|
+
window._ufq.push(['track', traits]);
|
5152
|
+
}
|
5153
|
+
}
|
5154
|
+
|
5155
|
+
});
|
5156
|
+
|
5157
|
+
});
|
5158
|
+
require.register("analytics/src/providers/uservoice.js", function(exports, require, module){
|
5159
|
+
// http://feedback.uservoice.com/knowledgebase/articles/225-how-do-i-pass-custom-data-through-the-widget-and-i
|
5160
|
+
|
5161
|
+
var Provider = require('../provider')
|
5162
|
+
, load = require('load-script')
|
5163
|
+
, alias = require('alias')
|
5164
|
+
, clone = require('clone');
|
5165
|
+
|
5166
|
+
|
5167
|
+
module.exports = Provider.extend({
|
5168
|
+
|
5169
|
+
name : 'UserVoice',
|
5170
|
+
|
5171
|
+
defaults : {
|
5172
|
+
// These first two options are required.
|
5173
|
+
widgetId : null,
|
5174
|
+
forumId : null,
|
5175
|
+
// Should we show the tab automatically?
|
5176
|
+
showTab : true,
|
5177
|
+
// There's tons of options for the tab.
|
5178
|
+
mode : 'full',
|
5179
|
+
primaryColor : '#cc6d00',
|
5180
|
+
linkColor : '#007dbf',
|
5181
|
+
defaultMode : 'support',
|
5182
|
+
tabLabel : 'Feedback & Support',
|
5183
|
+
tabColor : '#cc6d00',
|
5184
|
+
tabPosition : 'middle-right',
|
5185
|
+
tabInverted : false
|
5186
|
+
},
|
5187
|
+
|
5188
|
+
initialize : function (options, ready) {
|
5189
|
+
window.UserVoice = window.UserVoice || [];
|
5190
|
+
load('//widget.uservoice.com/' + options.widgetId + '.js', ready);
|
5191
|
+
|
5192
|
+
var optionsClone = clone(options);
|
5193
|
+
alias(optionsClone, {
|
5194
|
+
'forumId' : 'forum_id',
|
5195
|
+
'primaryColor' : 'primary_color',
|
5196
|
+
'linkColor' : 'link_color',
|
5197
|
+
'defaultMode' : 'default_mode',
|
5198
|
+
'tabLabel' : 'tab_label',
|
5199
|
+
'tabColor' : 'tab_color',
|
5200
|
+
'tabPosition' : 'tab_position',
|
5201
|
+
'tabInverted' : 'tab_inverted'
|
5202
|
+
});
|
5203
|
+
|
5204
|
+
// If we don't automatically show the tab, let them show it via
|
5205
|
+
// javascript. This is the default name for the function in their snippet.
|
5206
|
+
window.showClassicWidget = function (showWhat) {
|
5207
|
+
window.UserVoice.push([showWhat || 'showLightbox', 'classic_widget', optionsClone]);
|
5208
|
+
};
|
5209
|
+
|
5210
|
+
// If we *do* automatically show the tab, get on with it!
|
5211
|
+
if (options.showTab) {
|
5212
|
+
window.showClassicWidget('showTab');
|
5213
|
+
}
|
5214
|
+
},
|
5215
|
+
|
5216
|
+
identify : function (userId, traits) {
|
5217
|
+
// Pull the ID into traits.
|
5218
|
+
traits.id = userId;
|
5219
|
+
window.UserVoice.push(['setCustomFields', traits]);
|
5220
|
+
}
|
5221
|
+
|
5222
|
+
});
|
5223
|
+
});
|
5224
|
+
require.register("analytics/src/providers/vero.js", function(exports, require, module){
|
5225
|
+
// https://github.com/getvero/vero-api/blob/master/sections/js.md
|
5226
|
+
|
5227
|
+
var Provider = require('../provider')
|
5228
|
+
, isEmail = require('is-email')
|
5229
|
+
, load = require('load-script');
|
5230
|
+
|
5231
|
+
|
5232
|
+
module.exports = Provider.extend({
|
5233
|
+
|
5234
|
+
name : 'Vero',
|
5235
|
+
|
5236
|
+
key : 'apiKey',
|
5237
|
+
|
5238
|
+
defaults : {
|
5239
|
+
apiKey : null
|
5240
|
+
},
|
5241
|
+
|
5242
|
+
initialize : function (options, ready) {
|
5243
|
+
window._veroq = window._veroq || [];
|
5244
|
+
window._veroq.push(['init', { api_key: options.apiKey }]);
|
5245
|
+
load('//d3qxef4rp70elm.cloudfront.net/m.js');
|
5246
|
+
|
5247
|
+
// Vero creates a queue, so it's ready immediately.
|
5248
|
+
ready();
|
5249
|
+
},
|
5250
|
+
|
5251
|
+
identify : function (userId, traits) {
|
5252
|
+
// Don't do anything if we just have traits, because Vero
|
5253
|
+
// requires a `userId`.
|
5254
|
+
if (!userId || !traits.email) return;
|
5255
|
+
|
5256
|
+
// Vero takes the `userId` as part of the traits object.
|
5257
|
+
traits.id = userId;
|
5258
|
+
|
5259
|
+
window._veroq.push(['user', traits]);
|
5260
|
+
},
|
5261
|
+
|
5262
|
+
track : function (event, properties) {
|
5263
|
+
window._veroq.push(['track', event, properties]);
|
5264
|
+
}
|
5265
|
+
|
5266
|
+
});
|
5267
|
+
});
|
5268
|
+
require.register("analytics/src/providers/visual-website-optimizer.js", function(exports, require, module){
|
5269
|
+
// http://v2.visualwebsiteoptimizer.com/tools/get_tracking_code.php
|
5270
|
+
// http://visualwebsiteoptimizer.com/knowledge/integration-of-vwo-with-kissmetrics/
|
5271
|
+
|
5272
|
+
var each = require('each')
|
5273
|
+
, inherit = require('inherit')
|
5274
|
+
, nextTick = require('next-tick')
|
5275
|
+
, Provider = require('../provider');
|
5276
|
+
|
5277
|
+
|
5278
|
+
/**
|
5279
|
+
* Expose `VWO`.
|
5280
|
+
*/
|
5281
|
+
|
5282
|
+
module.exports = VWO;
|
5283
|
+
|
5284
|
+
|
5285
|
+
/**
|
5286
|
+
* `VWO` inherits from the generic `Provider`.
|
5287
|
+
*/
|
5288
|
+
|
5289
|
+
function VWO () {
|
5290
|
+
Provider.apply(this, arguments);
|
5291
|
+
}
|
5292
|
+
|
5293
|
+
inherit(VWO, Provider);
|
5294
|
+
|
5295
|
+
|
5296
|
+
/**
|
5297
|
+
* Name.
|
5298
|
+
*/
|
5299
|
+
|
5300
|
+
VWO.prototype.name = 'Visual Website Optimizer';
|
5301
|
+
|
5302
|
+
|
5303
|
+
/**
|
5304
|
+
* Default options.
|
5305
|
+
*/
|
5306
|
+
|
5307
|
+
VWO.prototype.defaults = {
|
5308
|
+
// Whether to replay variations into other integrations as traits.
|
5309
|
+
replay : true
|
5310
|
+
};
|
5311
|
+
|
5312
|
+
|
5313
|
+
/**
|
5314
|
+
* Initialize.
|
5315
|
+
*/
|
5316
|
+
|
5317
|
+
VWO.prototype.initialize = function (options, ready) {
|
5318
|
+
if (options.replay) this.replay();
|
5319
|
+
ready();
|
5320
|
+
};
|
5321
|
+
|
5322
|
+
|
5323
|
+
/**
|
5324
|
+
* Replay the experiments the user has seen as traits to all other integrations.
|
5325
|
+
* Wait for the next tick to replay so that the `analytics` object and all of
|
5326
|
+
* the integrations are fully initialized.
|
5327
|
+
*/
|
5328
|
+
|
5329
|
+
VWO.prototype.replay = function () {
|
5330
|
+
var analytics = this.analytics;
|
5331
|
+
nextTick(function () {
|
5332
|
+
experiments(function (err, traits) {
|
5333
|
+
if (traits) analytics.identify(traits);
|
5334
|
+
});
|
5335
|
+
});
|
5336
|
+
};
|
5337
|
+
|
5338
|
+
|
5339
|
+
/**
|
5340
|
+
* Get dictionary of experiment keys and variations.
|
5341
|
+
* http://visualwebsiteoptimizer.com/knowledge/integration-of-vwo-with-kissmetrics/
|
5342
|
+
*
|
5343
|
+
* @param {Function} callback Called with `err, experiments`.
|
5344
|
+
* @return {Object} Dictionary of experiments and variations.
|
5345
|
+
*/
|
5346
|
+
|
5347
|
+
function experiments (callback) {
|
5348
|
+
enqueue(function () {
|
5349
|
+
var data = {};
|
5350
|
+
var ids = window._vwo_exp_ids;
|
5351
|
+
if (!ids) return callback();
|
5352
|
+
each(ids, function (id) {
|
5353
|
+
var name = variation(id);
|
5354
|
+
if (name) data['Experiment: ' + id] = name;
|
5355
|
+
});
|
5356
|
+
callback(null, data);
|
5357
|
+
});
|
5358
|
+
}
|
5359
|
+
|
5360
|
+
|
5361
|
+
/**
|
5362
|
+
* Add a function to the VWO queue, creating one if it doesn't exist.
|
5363
|
+
*
|
5364
|
+
* @param {Function} fn Function to enqueue.
|
5365
|
+
*/
|
5366
|
+
|
5367
|
+
function enqueue (fn) {
|
5368
|
+
window._vis_opt_queue || (window._vis_opt_queue = []);
|
5369
|
+
window._vis_opt_queue.push(fn);
|
5370
|
+
}
|
5371
|
+
|
5372
|
+
|
5373
|
+
/**
|
5374
|
+
* Get the chosen variation's name from an experiment `id`.
|
5375
|
+
* http://visualwebsiteoptimizer.com/knowledge/integration-of-vwo-with-kissmetrics/
|
5376
|
+
*
|
5377
|
+
* @param {String} id ID of the experiment to read.
|
5378
|
+
* @return {String} Variation name.
|
5379
|
+
*/
|
5380
|
+
|
5381
|
+
function variation (id) {
|
5382
|
+
var experiments = window._vwo_exp;
|
5383
|
+
if (!experiments) return null;
|
5384
|
+
var experiment = experiments[id];
|
5385
|
+
var variationId = experiment.combination_chosen;
|
5386
|
+
return variationId ? experiment.comb_n[variationId] : null;
|
5387
|
+
}
|
5388
|
+
});
|
5389
|
+
require.register("analytics/src/providers/woopra.js", function(exports, require, module){
|
5390
|
+
// http://www.woopra.com/docs/setup/javascript-tracking/
|
5391
|
+
|
5392
|
+
var Provider = require('../provider')
|
5393
|
+
, each = require('each')
|
5394
|
+
, extend = require('extend')
|
5395
|
+
, isEmail = require('is-email')
|
5396
|
+
, load = require('load-script')
|
5397
|
+
, type = require('type')
|
5398
|
+
, user = require('../user');
|
5399
|
+
|
5400
|
+
|
5401
|
+
module.exports = Provider.extend({
|
5402
|
+
|
5403
|
+
name : 'Woopra',
|
5404
|
+
|
5405
|
+
key : 'domain',
|
5406
|
+
|
5407
|
+
defaults : {
|
5408
|
+
domain : null
|
5409
|
+
},
|
5410
|
+
|
5411
|
+
initialize : function (options, ready) {
|
5412
|
+
// Woopra gives us a nice ready callback.
|
5413
|
+
var self = this;
|
5414
|
+
|
5415
|
+
window.woopraReady = function (tracker) {
|
5416
|
+
tracker.setDomain(self.options.domain);
|
5417
|
+
tracker.setIdleTimeout(300000);
|
5418
|
+
|
5419
|
+
var userId = user.id()
|
5420
|
+
, traits = user.traits();
|
5421
|
+
|
5422
|
+
addTraits(userId, traits, tracker);
|
5423
|
+
tracker.track();
|
5424
|
+
|
5425
|
+
ready();
|
5426
|
+
return false;
|
5427
|
+
};
|
5428
|
+
|
5429
|
+
load('//static.woopra.com/js/woopra.js');
|
5430
|
+
},
|
5431
|
+
|
5432
|
+
identify : function (userId, traits) {
|
5433
|
+
// We aren't guaranteed a tracker.
|
5434
|
+
if (!window.woopraTracker) return;
|
5435
|
+
addTraits(userId, traits, window.woopraTracker);
|
5436
|
+
},
|
5437
|
+
|
5438
|
+
track : function (event, properties) {
|
5439
|
+
// We aren't guaranteed a tracker.
|
5440
|
+
if (!window.woopraTracker) return;
|
5441
|
+
|
5442
|
+
// Woopra takes its `event` as the `name` key.
|
5443
|
+
properties || (properties = {});
|
5444
|
+
properties.name = event;
|
5445
|
+
|
5446
|
+
window.woopraTracker.pushEvent(properties);
|
5447
|
+
}
|
5448
|
+
|
5449
|
+
});
|
5450
|
+
|
5451
|
+
|
5452
|
+
/**
|
5453
|
+
* Convenience function for updating the userId and traits.
|
5454
|
+
*
|
5455
|
+
* @param {String} userId The user's ID.
|
5456
|
+
* @param {Object} traits The user's traits.
|
5457
|
+
* @param {Tracker} tracker The Woopra tracker object.
|
5458
|
+
*/
|
5459
|
+
|
5460
|
+
function addTraits (userId, traits, tracker) {
|
5461
|
+
// Move a `userId` into `traits`.
|
5462
|
+
if (userId) traits.id = userId;
|
5463
|
+
each(traits, function (key, value) {
|
5464
|
+
// Woopra seems to only support strings as trait values.
|
5465
|
+
if ('string' === type(value)) tracker.addVisitorProperty(key, value);
|
5466
|
+
});
|
5467
|
+
}
|
5468
|
+
});
|
5469
|
+
require.alias("avetisk-defaults/index.js", "analytics/deps/defaults/index.js");
|
5470
|
+
require.alias("avetisk-defaults/index.js", "defaults/index.js");
|
5471
|
+
|
5472
|
+
require.alias("component-clone/index.js", "analytics/deps/clone/index.js");
|
5473
|
+
require.alias("component-clone/index.js", "clone/index.js");
|
5474
|
+
require.alias("component-type/index.js", "component-clone/deps/type/index.js");
|
5475
|
+
|
5476
|
+
require.alias("component-cookie/index.js", "analytics/deps/cookie/index.js");
|
5477
|
+
require.alias("component-cookie/index.js", "cookie/index.js");
|
5478
|
+
|
5479
|
+
require.alias("component-each/index.js", "analytics/deps/each/index.js");
|
5480
|
+
require.alias("component-each/index.js", "each/index.js");
|
5481
|
+
require.alias("component-type/index.js", "component-each/deps/type/index.js");
|
5482
|
+
|
5483
|
+
require.alias("component-event/index.js", "analytics/deps/event/index.js");
|
5484
|
+
require.alias("component-event/index.js", "event/index.js");
|
5485
|
+
|
5486
|
+
require.alias("component-inherit/index.js", "analytics/deps/inherit/index.js");
|
5487
|
+
require.alias("component-inherit/index.js", "inherit/index.js");
|
5488
|
+
|
5489
|
+
require.alias("component-object/index.js", "analytics/deps/object/index.js");
|
5490
|
+
require.alias("component-object/index.js", "object/index.js");
|
5491
|
+
|
5492
|
+
require.alias("component-querystring/index.js", "analytics/deps/querystring/index.js");
|
5493
|
+
require.alias("component-querystring/index.js", "querystring/index.js");
|
5494
|
+
require.alias("component-trim/index.js", "component-querystring/deps/trim/index.js");
|
5495
|
+
|
5496
|
+
require.alias("component-type/index.js", "analytics/deps/type/index.js");
|
5497
|
+
require.alias("component-type/index.js", "type/index.js");
|
5498
|
+
|
5499
|
+
require.alias("component-url/index.js", "analytics/deps/url/index.js");
|
5500
|
+
require.alias("component-url/index.js", "url/index.js");
|
5501
|
+
|
5502
|
+
require.alias("segmentio-after/index.js", "analytics/deps/after/index.js");
|
5503
|
+
require.alias("segmentio-after/index.js", "after/index.js");
|
5504
|
+
|
5505
|
+
require.alias("segmentio-alias/index.js", "analytics/deps/alias/index.js");
|
5506
|
+
require.alias("segmentio-alias/index.js", "alias/index.js");
|
5507
|
+
|
5508
|
+
require.alias("segmentio-bind-all/index.js", "analytics/deps/bind-all/index.js");
|
5509
|
+
require.alias("segmentio-bind-all/index.js", "analytics/deps/bind-all/index.js");
|
5510
|
+
require.alias("segmentio-bind-all/index.js", "bind-all/index.js");
|
5511
|
+
require.alias("component-bind/index.js", "segmentio-bind-all/deps/bind/index.js");
|
5512
|
+
|
5513
|
+
require.alias("component-type/index.js", "segmentio-bind-all/deps/type/index.js");
|
5514
|
+
|
5515
|
+
require.alias("segmentio-bind-all/index.js", "segmentio-bind-all/index.js");
|
5516
|
+
|
5517
|
+
require.alias("segmentio-canonical/index.js", "analytics/deps/canonical/index.js");
|
5518
|
+
require.alias("segmentio-canonical/index.js", "canonical/index.js");
|
5519
|
+
|
5520
|
+
require.alias("segmentio-extend/index.js", "analytics/deps/extend/index.js");
|
5521
|
+
require.alias("segmentio-extend/index.js", "extend/index.js");
|
5522
|
+
|
5523
|
+
require.alias("segmentio-is-email/index.js", "analytics/deps/is-email/index.js");
|
5524
|
+
require.alias("segmentio-is-email/index.js", "is-email/index.js");
|
5525
|
+
|
5526
|
+
require.alias("segmentio-is-meta/index.js", "analytics/deps/is-meta/index.js");
|
5527
|
+
require.alias("segmentio-is-meta/index.js", "is-meta/index.js");
|
5528
|
+
|
5529
|
+
require.alias("segmentio-json/index.js", "analytics/deps/json/index.js");
|
5530
|
+
require.alias("segmentio-json/index.js", "json/index.js");
|
5531
|
+
require.alias("component-json-fallback/index.js", "segmentio-json/deps/json-fallback/index.js");
|
5532
|
+
|
5533
|
+
require.alias("segmentio-load-date/index.js", "analytics/deps/load-date/index.js");
|
5534
|
+
require.alias("segmentio-load-date/index.js", "load-date/index.js");
|
5535
|
+
|
5536
|
+
require.alias("segmentio-load-script/index.js", "analytics/deps/load-script/index.js");
|
5537
|
+
require.alias("segmentio-load-script/index.js", "load-script/index.js");
|
5538
|
+
require.alias("component-type/index.js", "segmentio-load-script/deps/type/index.js");
|
5539
|
+
|
5540
|
+
require.alias("segmentio-new-date/index.js", "analytics/deps/new-date/index.js");
|
5541
|
+
require.alias("segmentio-new-date/index.js", "new-date/index.js");
|
5542
|
+
require.alias("segmentio-type/index.js", "segmentio-new-date/deps/type/index.js");
|
5543
|
+
|
5544
|
+
require.alias("segmentio-on-body/index.js", "analytics/deps/on-body/index.js");
|
5545
|
+
require.alias("segmentio-on-body/index.js", "on-body/index.js");
|
5546
|
+
require.alias("component-each/index.js", "segmentio-on-body/deps/each/index.js");
|
5547
|
+
require.alias("component-type/index.js", "component-each/deps/type/index.js");
|
5548
|
+
|
5549
|
+
require.alias("segmentio-store.js/store.js", "analytics/deps/store/store.js");
|
5550
|
+
require.alias("segmentio-store.js/store.js", "analytics/deps/store/index.js");
|
5551
|
+
require.alias("segmentio-store.js/store.js", "store/index.js");
|
5552
|
+
require.alias("segmentio-json/index.js", "segmentio-store.js/deps/json/index.js");
|
5553
|
+
require.alias("component-json-fallback/index.js", "segmentio-json/deps/json-fallback/index.js");
|
5554
|
+
|
5555
|
+
require.alias("segmentio-store.js/store.js", "segmentio-store.js/index.js");
|
5556
|
+
|
5557
|
+
require.alias("segmentio-top-domain/index.js", "analytics/deps/top-domain/index.js");
|
5558
|
+
require.alias("segmentio-top-domain/index.js", "analytics/deps/top-domain/index.js");
|
5559
|
+
require.alias("segmentio-top-domain/index.js", "top-domain/index.js");
|
5560
|
+
require.alias("component-url/index.js", "segmentio-top-domain/deps/url/index.js");
|
5561
|
+
|
5562
|
+
require.alias("segmentio-top-domain/index.js", "segmentio-top-domain/index.js");
|
5563
|
+
|
5564
|
+
require.alias("timoxley-next-tick/index.js", "analytics/deps/next-tick/index.js");
|
5565
|
+
require.alias("timoxley-next-tick/index.js", "next-tick/index.js");
|
5566
|
+
|
5567
|
+
require.alias("yields-prevent/index.js", "analytics/deps/prevent/index.js");
|
5568
|
+
require.alias("yields-prevent/index.js", "prevent/index.js");
|
5569
|
+
|
5570
|
+
require.alias("analytics/src/index.js", "analytics/index.js");
|
5571
|
+
|
5572
|
+
if (typeof exports == "object") {
|
5573
|
+
module.exports = require("analytics");
|
5574
|
+
} else if (typeof define == "function" && define.amd) {
|
5575
|
+
define(function(){ return require("analytics"); });
|
5576
|
+
} else {
|
5577
|
+
this["analytics"] = require("analytics");
|
5578
|
+
}})();
|