analytics-js-rails 0.11.0.rc1 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}})();
|