diff --git a/packages/analytics-plugin-churn-zero/.babelrc b/packages/analytics-plugin-churn-zero/.babelrc
new file mode 100644
index 00000000..b5e3023e
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/.babelrc
@@ -0,0 +1,9 @@
+{
+ "presets": [
+ [
+ "@babel/env", {
+ "modules": false
+ }
+ ]
+ ]
+}
diff --git a/packages/analytics-plugin-churn-zero/.gitignore b/packages/analytics-plugin-churn-zero/.gitignore
new file mode 100644
index 00000000..e9d65964
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/.gitignore
@@ -0,0 +1,13 @@
+dist
+node_modules
+lib
+yarn.lock
+
+*.log
+
+# IDE stuff
+**/.idea
+
+# OS stuff
+.DS_Store
+.tmp
\ No newline at end of file
diff --git a/packages/analytics-plugin-churn-zero/CHANGELOG.md b/packages/analytics-plugin-churn-zero/CHANGELOG.md
new file mode 100644
index 00000000..29eeacbc
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/CHANGELOG.md
@@ -0,0 +1,12 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+
+## [0.0.1](https://github.com/DavidWells/analytics/compare/analytics-plugin-churn-zero@0.0.1) (2024-08-27)
+
+**Note:** Initial version for package analytics-plugin-churn-zero
+
+### Features
+
+- **plugin-churn-zero:** add churn-zero plugin ([](https://github.com/DavidWells/analytics/commit/))
diff --git a/packages/analytics-plugin-churn-zero/README.md b/packages/analytics-plugin-churn-zero/README.md
new file mode 100644
index 00000000..b750fc3a
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/README.md
@@ -0,0 +1,336 @@
+
+# ChurnZero plugin for `analytics`
+
+Integration with ChurnZero for [analytics](https://www.npmjs.com/package/analytics)
+
+This analytics plugin will load ChurnZero's client side tracking script into your application and send custom events, page views, and identify visitors inside ChurnZero.
+
+[View the docs](https://getanalytics.io/plugins/churn-zero/)
+
+
+
+Click to expand
+
+- [Installation](#installation)
+- [How to use](#how-to-use)
+- [Platforms Supported](#platforms-supported)
+- [Browser usage](#browser-usage)
+ - [Browser API](#browser-api)
+ - [Configuration options for browser](#configuration-options-for-browser)
+- [Server-side usage](#server-side-usage)
+ - [Server-side API](#server-side-api)
+ - [Configuration options for server-side](#configuration-options-for-server-side)
+- [Additional examples](#additional-examples)
+
+
+
+
+## Installation
+
+Install `analytics` and `@analytics/churn-zero` packages
+
+```bash
+npm install analytics
+npm install @analytics/churn-zero
+```
+
+
+
+## How to use
+
+The `@analytics/churn-zero` package works in [the browser](#browser-usage) and [server-side in Node.js](#server-side-usage). To use, install the package, include in your project and initialize the plugin with [analytics](https://www.npmjs.com/package/analytics).
+
+Below is an example of how to use the browser plugin.
+
+```js
+import Analytics from 'analytics'
+import churnZeroPlugin from '@analytics/churn-zero'
+
+const analytics = Analytics({
+ app: 'awesome-app',
+ plugins: [
+ // This will load crazy egg on to the page
+ churnZeroPlugin({
+ accountId: '1234578'
+ })
+ ]
+})
+
+/* Track a page view */
+analytics.page()
+
+/* Track a custom event */
+analytics.track('cartCheckout', {
+ item: 'pink socks',
+ price: 20
+})
+
+/* Identify a visitor */
+analytics.identify('user-id-xyz', {
+ firstName: 'bill',
+ lastName: 'murray'
+})
+
+```
+
+After initializing `analytics` with the `churnZeroPlugin` plugin, data will be sent into ChurnZero whenever [analytics.page](https://getanalytics.io/api/#analyticspage), [analytics.track](https://getanalytics.io/api/#analyticstrack), or [analytics.identify](https://getanalytics.io/api/#analyticsidentify) are called.
+
+See [additional implementation examples](#additional-examples) for more details on using in your project.
+
+## Platforms Supported
+
+The `@analytics/churn-zero` package works in [the browser](#browser-usage) and [server-side in Node.js](#server-side-usage)
+
+## Browser usage
+
+The ChurnZero client side browser plugin works with these analytic api methods:
+
+- **[analytics.identify](https://getanalytics.io/api/#analyticsidentify)** - Identify visitors and send details to ChurnZero
+- **[analytics.page](https://getanalytics.io/api/#analyticspage)** - Sends page views into ChurnZero
+- **[analytics.track](https://getanalytics.io/api/#analyticstrack)** - Track custom events and send to ChurnZero
+
+### Browser API
+
+```js
+import Analytics from 'analytics'
+import churnZeroPlugin from '@analytics/churn-zero'
+
+const analytics = Analytics({
+ app: 'awesome-app',
+ plugins: [
+ // This will load crazy egg on to the page
+ churnZeroPlugin({
+ accountId: '1234578'
+ })
+ ]
+})
+
+```
+
+### Configuration options for browser
+
+| Option | description |
+|:---------------------------|:-----------|
+| `accountId`
**required** - string| ChurnZero account ID |
+| `scriptInclude`
_optional_ - boolean| Load ChurnZero script into page |
+| `options`
_optional_ - object| ChurnZero script options |
+
+## Server-side usage
+
+The ChurnZero server-side node.js plugin works with these analytic api methods:
+
+- **[analytics.page](https://getanalytics.io/api/#analyticspage)** - Sends page views into ChurnZero
+- **[analytics.track](https://getanalytics.io/api/#analyticstrack)** - Track custom events and send to ChurnZero
+- **[analytics.identify](https://getanalytics.io/api/#analyticsidentify)** - Identify visitors and send details to ChurnZero
+
+### Server-side API
+
+```js
+import Analytics from 'analytics'
+import churnZeroPlugin from '@analytics/churn-zero'
+
+const analytics = Analytics({
+ app: 'awesome-app',
+ plugins: [
+ churnZeroPlugin({
+ apiKey: 'abc123'
+ })
+ ]
+})
+
+```
+
+### Configuration options for server-side
+
+| Option | description |
+|:---------------------------|:-----------|
+| `apiKey`
**required** - string| ChurnZero API key |
+
+
+## Additional examples
+
+Below are additional implementation examples.
+
+
+ Server-side ES6
+
+ ```js
+ import Analytics from 'analytics'
+ import churnZeroPlugin from '@analytics/churn-zero'
+
+ const analytics = Analytics({
+ app: 'awesome-app',
+ plugins: [
+ churnZeroPlugin({
+ apiKey: 'abc123'
+ })
+ // ...other plugins
+ ]
+ })
+
+ /* Track a page view */
+ analytics.page()
+
+ /* Track a custom event */
+ analytics.track('cartCheckout', {
+ item: 'pink socks',
+ price: 20
+ })
+
+ /* Identify a visitor */
+ analytics.identify('user-id-xyz', {
+ firstName: 'bill',
+ lastName: 'murray'
+ })
+
+ ```
+
+
+
+
+ Server-side Node.js with common JS
+
+ If using node, you will want to import the `.default`
+
+ ```js
+ const analyticsLib = require('analytics').default
+ const churnZeroPlugin = require('@analytics/churn-zero').default
+
+ const analytics = analyticsLib({
+ app: 'my-app-name',
+ plugins: [
+ churnZeroPlugin({
+ apiKey: 'abc123'
+ })
+ ]
+ })
+
+ /* Track a page view */
+ analytics.page()
+
+ /* Track a custom event */
+ analytics.track('cartCheckout', {
+ item: 'pink socks',
+ price: 20
+ })
+
+ /* Identify a visitor */
+ analytics.identify('user-id-xyz', {
+ firstName: 'bill',
+ lastName: 'murray'
+ })
+
+ ```
+
+
+
+
+ Using in HTML
+
+ Below is an example of importing via the unpkg CDN. Please note this will pull in the latest version of the package.
+
+ ```html
+
+
+
+ Using @analytics/churn-zero in HTML
+
+
+
+
+
+ ....
+
+
+
+ ```
+
+
+
+
+ Using in HTML via ES Modules
+
+ Using `@analytics/churn-zero` in ESM modules.
+
+ ```html
+
+
+
+ Using @analytics/churn-zero in HTML via ESModules
+
+
+
+
+ ....
+
+
+
+ ```
+
+
+
+
+
diff --git a/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.cjs.js b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.cjs.js
new file mode 100644
index 00000000..212bbd62
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.cjs.js
@@ -0,0 +1,89 @@
+'use strict';
+
+require('unfetch');
+
+/* global ChurnZero */
+
+/**
+ * ChurnZero plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://support.churnzero.com/hc/en-us/articles/360004683552-Integrate-ChurnZero-using-Javascript
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero AppKey
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * This will load ChurnZero on to the page
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin() {
+ var pluginConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ return {
+ name: 'churn-zero',
+ config: pluginConfig,
+ initialize: function initialize(_ref) {
+ var config = _ref.config;
+ var appKey = config.appKey,
+ subdomain = config.subdomain;
+ if (!appKey) {
+ throw new Error('No ChurnZero appKey defined');
+ }
+ if (!subdomain) {
+ throw new Error('No ChurnZero subdomain defined');
+ }
+
+ // Create script & append to DOM
+ var script = document.createElement('script');
+ var firstScript = document.getElementsByTagName('script')[0];
+ script.type = 'text/javascript';
+ script.async = true;
+ script.src = "https://".concat(subdomain, ".churnzero.net/churnzero.js");
+ firstScript.parentNode.insertBefore(script, firstScript);
+ },
+ identify: function identify(_ref2) {
+ var payload = _ref2.payload,
+ config = _ref2.config;
+ var _payload$traits = payload.traits,
+ company = _payload$traits.company,
+ email = _payload$traits.email,
+ firstName = _payload$traits.firstName,
+ lastName = _payload$traits.lastName;
+ if (typeof ChurnZero === 'undefined') return;
+ if (config.appKey) {
+ ChurnZero.push(['setAppKey', config.appKey]);
+ }
+ if (company && company.id && email) {
+ ChurnZero.push(['setContact', company.id, email]);
+ }
+ if (firstName) {
+ ChurnZero.push(['setAttribute', 'contact', 'FirstName', firstName]);
+ }
+ if (lastName) {
+ ChurnZero.push(['setAttribute', 'contact', 'LastName', lastName]);
+ }
+ if (email) {
+ ChurnZero.push(['setAttribute', 'contact', 'Email', email]);
+ }
+ },
+ track: function track(_ref3) {
+ var payload = _ref3.payload,
+ config = _ref3.config;
+ if (typeof ChurnZero === 'undefined') return;
+ if (config.whitelistedEvents && !config.whitelistedEvents.includes(payload.event)) return;
+ ChurnZero.push(['trackEvent', payload.event, undefined, undefined, payload.properties]);
+ },
+ loaded: function loaded() {
+ return !!window.ChurnZero;
+ }
+ };
+}
+
+/* This module will shake out unused code and work in browser and node 🎉 */
+var index = churnZeroPlugin ;
+
+module.exports = index;
diff --git a/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.es.js b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.es.js
new file mode 100644
index 00000000..729c3c6a
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.browser.es.js
@@ -0,0 +1,87 @@
+import 'unfetch';
+
+/* global ChurnZero */
+
+/**
+ * ChurnZero plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://support.churnzero.com/hc/en-us/articles/360004683552-Integrate-ChurnZero-using-Javascript
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero AppKey
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * This will load ChurnZero on to the page
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin() {
+ var pluginConfig = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+ return {
+ name: 'churn-zero',
+ config: pluginConfig,
+ initialize: function initialize(_ref) {
+ var config = _ref.config;
+ var appKey = config.appKey,
+ subdomain = config.subdomain;
+ if (!appKey) {
+ throw new Error('No ChurnZero appKey defined');
+ }
+ if (!subdomain) {
+ throw new Error('No ChurnZero subdomain defined');
+ }
+
+ // Create script & append to DOM
+ var script = document.createElement('script');
+ var firstScript = document.getElementsByTagName('script')[0];
+ script.type = 'text/javascript';
+ script.async = true;
+ script.src = "https://".concat(subdomain, ".churnzero.net/churnzero.js");
+ firstScript.parentNode.insertBefore(script, firstScript);
+ },
+ identify: function identify(_ref2) {
+ var payload = _ref2.payload,
+ config = _ref2.config;
+ var _payload$traits = payload.traits,
+ company = _payload$traits.company,
+ email = _payload$traits.email,
+ firstName = _payload$traits.firstName,
+ lastName = _payload$traits.lastName;
+ if (typeof ChurnZero === 'undefined') return;
+ if (config.appKey) {
+ ChurnZero.push(['setAppKey', config.appKey]);
+ }
+ if (company && company.id && email) {
+ ChurnZero.push(['setContact', company.id, email]);
+ }
+ if (firstName) {
+ ChurnZero.push(['setAttribute', 'contact', 'FirstName', firstName]);
+ }
+ if (lastName) {
+ ChurnZero.push(['setAttribute', 'contact', 'LastName', lastName]);
+ }
+ if (email) {
+ ChurnZero.push(['setAttribute', 'contact', 'Email', email]);
+ }
+ },
+ track: function track(_ref3) {
+ var payload = _ref3.payload,
+ config = _ref3.config;
+ if (typeof ChurnZero === 'undefined') return;
+ if (config.whitelistedEvents && !config.whitelistedEvents.includes(payload.event)) return;
+ ChurnZero.push(['trackEvent', payload.event, undefined, undefined, payload.properties]);
+ },
+ loaded: function loaded() {
+ return !!window.ChurnZero;
+ }
+ };
+}
+
+/* This module will shake out unused code and work in browser and node 🎉 */
+var index = churnZeroPlugin ;
+
+export { index as default };
diff --git a/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.cjs.js b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.cjs.js
new file mode 100644
index 00000000..1fc57383
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.cjs.js
@@ -0,0 +1,112 @@
+'use strict';
+
+var fetch = require('unfetch');
+
+function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
+
+function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
+function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
+function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
+function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
+function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
+
+/**
+ * Custify server plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://docs.churn-zero.com/
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero API key
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin(_ref) {
+ var appKey = _ref.appKey,
+ subdomain = _ref.subdomain,
+ accountExternalId = _ref.accountExternalId,
+ contactExternalId = _ref.contactExternalId;
+ var _loaded = false;
+ return {
+ name: 'churn-zero',
+ config: {
+ appKey: appKey,
+ subdomain: subdomain,
+ accountExternalId: accountExternalId,
+ contactExternalId: contactExternalId
+ },
+ track: function track(_ref2) {
+ var payload = _ref2.payload;
+ var _payload$traits = payload.traits,
+ company = _payload$traits.company,
+ email = _payload$traits.email,
+ event = _payload$traits.event,
+ properties = _payload$traits.properties;
+ makeChurnZeroRequest(config, {
+ action: 'trackEvent',
+ eventName: event,
+ cf_metadata: properties,
+ accountExternalId: company ? company.id : undefined,
+ contactExternalId: email
+ });
+ },
+ identify: function identify(_ref3) {
+ var payload = _ref3.payload;
+ var _payload$traits2 = payload.traits,
+ company = _payload$traits2.company,
+ email = _payload$traits2.email,
+ name = _payload$traits2.name,
+ firstName = _payload$traits2.firstName,
+ lastName = _payload$traits2.lastName;
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'account',
+ attr_Name: name,
+ accountExternalId: company.id,
+ contactExternalId: email
+ });
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'contact',
+ attr_FirstName: firstName,
+ attr_LastName: lastName,
+ attr_Email: email,
+ accountExternalId: company.id,
+ contactExternalId: email
+ });
+ },
+ loaded: function loaded() {
+ return _loaded;
+ }
+ };
+}
+function makeChurnZeroRequest(_ref4) {
+ var config = _ref4.config,
+ body = _ref4.body;
+ return fetch__default["default"]("https://".concat(config.subdomain, ".churnzero.net/i"), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache'
+ },
+ body: JSON.stringify(_objectSpread(_objectSpread({
+ appKey: config.appKey
+ }, body), {}, {
+ accountExternalId: body.accountExternalId || config.accountExternalId,
+ contactExternalId: body.contactExternalId || config.contactExternalId
+ }))
+ });
+}
+
+/* This module will shake out unused code and work in browser and node 🎉 */
+var index = churnZeroPlugin;
+
+module.exports = index;
diff --git a/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.es.js b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.es.js
new file mode 100644
index 00000000..908f9e64
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/lib/analytics-plugin-churn-zero.es.js
@@ -0,0 +1,106 @@
+import fetch from 'unfetch';
+
+function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
+function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
+function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
+function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
+function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
+function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
+
+/**
+ * Custify server plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://docs.churn-zero.com/
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero API key
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin(_ref) {
+ var appKey = _ref.appKey,
+ subdomain = _ref.subdomain,
+ accountExternalId = _ref.accountExternalId,
+ contactExternalId = _ref.contactExternalId;
+ var _loaded = false;
+ return {
+ name: 'churn-zero',
+ config: {
+ appKey: appKey,
+ subdomain: subdomain,
+ accountExternalId: accountExternalId,
+ contactExternalId: contactExternalId
+ },
+ track: function track(_ref2) {
+ var payload = _ref2.payload;
+ var _payload$traits = payload.traits,
+ company = _payload$traits.company,
+ email = _payload$traits.email,
+ event = _payload$traits.event,
+ properties = _payload$traits.properties;
+ makeChurnZeroRequest(config, {
+ action: 'trackEvent',
+ eventName: event,
+ cf_metadata: properties,
+ accountExternalId: company ? company.id : undefined,
+ contactExternalId: email
+ });
+ },
+ identify: function identify(_ref3) {
+ var payload = _ref3.payload;
+ var _payload$traits2 = payload.traits,
+ company = _payload$traits2.company,
+ email = _payload$traits2.email,
+ name = _payload$traits2.name,
+ firstName = _payload$traits2.firstName,
+ lastName = _payload$traits2.lastName;
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'account',
+ attr_Name: name,
+ accountExternalId: company.id,
+ contactExternalId: email
+ });
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'contact',
+ attr_FirstName: firstName,
+ attr_LastName: lastName,
+ attr_Email: email,
+ accountExternalId: company.id,
+ contactExternalId: email
+ });
+ },
+ loaded: function loaded() {
+ return _loaded;
+ }
+ };
+}
+function makeChurnZeroRequest(_ref4) {
+ var config = _ref4.config,
+ body = _ref4.body;
+ return fetch("https://".concat(config.subdomain, ".churnzero.net/i"), {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache'
+ },
+ body: JSON.stringify(_objectSpread(_objectSpread({
+ appKey: config.appKey
+ }, body), {}, {
+ accountExternalId: body.accountExternalId || config.accountExternalId,
+ contactExternalId: body.contactExternalId || config.contactExternalId
+ }))
+ });
+}
+
+/* This module will shake out unused code and work in browser and node 🎉 */
+var index = churnZeroPlugin;
+
+export { index as default };
diff --git a/packages/analytics-plugin-churn-zero/package.json b/packages/analytics-plugin-churn-zero/package.json
new file mode 100644
index 00000000..44042fe0
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "@analytics/churn-zero",
+ "version": "0.0.1",
+ "description": "Churnzero integration for 'analytics' module for browser & node",
+ "projectMeta": {
+ "provider": {
+ "name": "ChurnZero",
+ "url": "https://www.churnzero.com/"
+ },
+ "platforms": {
+ "browser": "./src/browser.js",
+ "node": "./src/node.js"
+ }
+ },
+ "keywords": [
+ "analytics",
+ "analytics-project",
+ "analytics-plugin",
+ "churn-zero"
+ ],
+ "author": "Ahmed Onawale ",
+ "license": "MIT",
+ "scripts": {
+ "docs": "node ../analytics-cli/bin/run docs",
+ "build": "node ../../scripts/build/index.js",
+ "watch": "node ../../scripts/build/_watch.js",
+ "release:patch": "npm version patch && npm publish",
+ "release:minor": "npm version minor && npm publish",
+ "release:major": "npm version major && npm publish",
+ "es": "../../node_modules/.bin/babel-node ./testBabel.js"
+ },
+ "main": "lib/analytics-plugin-churn-zero.cjs.js",
+ "globalName": "analyticsChurnzero",
+ "jsnext:main": "lib/analytics-plugin-churn-zero.es.js",
+ "module": "lib/analytics-plugin-churn-zero.es.js",
+ "browser": {
+ "./lib/analytics-plugin-churn-zero.cjs.js": "./lib/analytics-plugin-churn-zero.browser.cjs.js",
+ "./lib/analytics-plugin-churn-zero.es.js": "./lib/analytics-plugin-churn-zero.browser.es.js"
+ },
+ "files": [
+ "dist",
+ "lib",
+ "README.md"
+ ],
+ "homepage": "https://github.com/DavidWells/analytics#readme",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/DavidWells/analytics.git"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.2.2",
+ "@babel/preset-env": "^7.3.1"
+ },
+ "dependencies": {
+ "unfetch": "^4.2.0"
+ }
+}
diff --git a/packages/analytics-plugin-churn-zero/src/browser.js b/packages/analytics-plugin-churn-zero/src/browser.js
new file mode 100644
index 00000000..81d34c3b
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/src/browser.js
@@ -0,0 +1,77 @@
+/* global ChurnZero */
+
+/**
+ * ChurnZero plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://support.churnzero.com/hc/en-us/articles/360004683552-Integrate-ChurnZero-using-Javascript
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero AppKey
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * This will load ChurnZero on to the page
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin(pluginConfig = {}) {
+ return {
+ name: 'churn-zero',
+ config: pluginConfig,
+ initialize: ({ config }) => {
+ const { appKey, subdomain } = config
+ if (!appKey) {
+ throw new Error('No ChurnZero appKey defined')
+ }
+ if (!subdomain) {
+ throw new Error('No ChurnZero subdomain defined')
+ }
+
+ // Create script & append to DOM
+ const script = document.createElement('script');
+ const firstScript = document.getElementsByTagName('script')[0];
+ script.type = 'text/javascript';
+ script.async = true;
+ script.src = `https://${subdomain}.churnzero.net/churnzero.js`;
+ firstScript.parentNode.insertBefore(script, firstScript);
+ },
+ identify: ({ payload, config }) => {
+ const { company, email, firstName, lastName } = payload.traits
+
+ if (typeof ChurnZero === 'undefined') return
+
+ if (config.appKey) {
+ ChurnZero.push(['setAppKey', config.appKey]);
+ }
+
+ if (company && company.id && email) {
+ ChurnZero.push(['setContact', company.id, email]);
+ }
+
+ if (firstName) {
+ ChurnZero.push(['setAttribute', 'contact', 'FirstName', firstName]);
+ }
+ if (lastName) {
+ ChurnZero.push(['setAttribute', 'contact', 'LastName', lastName]);
+ }
+ if (email) {
+ ChurnZero.push(['setAttribute', 'contact', 'Email', email]);
+ }
+ },
+ track: ({ payload, config }) => {
+ if (typeof ChurnZero === 'undefined') return
+
+ if (config.whitelistedEvents && !config.whitelistedEvents.includes(payload.event)) return
+
+ ChurnZero.push(['trackEvent', payload.event, undefined, undefined, payload.properties]);
+ },
+ loaded: () => {
+ return !!window.ChurnZero
+ },
+ }
+}
+
+export default churnZeroPlugin
diff --git a/packages/analytics-plugin-churn-zero/src/index.js b/packages/analytics-plugin-churn-zero/src/index.js
new file mode 100644
index 00000000..77aac893
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/src/index.js
@@ -0,0 +1,5 @@
+import nodeCode from './node'
+import browser from './browser'
+
+/* This module will shake out unused code and work in browser and node 🎉 */
+export default process.browser ? browser : nodeCode
diff --git a/packages/analytics-plugin-churn-zero/src/node.js b/packages/analytics-plugin-churn-zero/src/node.js
new file mode 100644
index 00000000..cba9591f
--- /dev/null
+++ b/packages/analytics-plugin-churn-zero/src/node.js
@@ -0,0 +1,81 @@
+import fetch from 'unfetch'
+
+/**
+ * Custify server plugin
+ * @link https://getanalytics.io/plugins/churn-zero
+ * @link https://docs.churn-zero.com/
+ * @param {object} pluginConfig - Plugin settings
+ * @param {string} pluginConfig.appKey - ChurnZero API key
+ * @param {string} pluginConfig.subdomain - ChurnZero AppKey
+ * @param {string} pluginConfig.whitelistedEvents - An optional list of events to track
+ * @return {AnalyticsPlugin}
+ * @example
+ *
+ * churnZeroPlugin({
+ * appKey: '1234578'
+ * subdomain: 'mycompanydomain'
+ * })
+ */
+function churnZeroPlugin({ appKey, subdomain, accountExternalId, contactExternalId }) {
+ let loaded = false;
+ return {
+ name: 'churn-zero',
+ config: {
+ appKey,
+ subdomain,
+ accountExternalId,
+ contactExternalId,
+ },
+ track: ({ payload }) => {
+ const { company, email, event, properties } = payload.traits
+
+ makeChurnZeroRequest(config, {
+ action: 'trackEvent',
+ eventName: event,
+ cf_metadata: properties,
+ accountExternalId: company ? company.id : undefined,
+ contactExternalId: email,
+ });
+ },
+ identify: ({ payload }) => {
+ const { company, email, name, firstName, lastName } = payload.traits
+
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'account',
+ attr_Name: name,
+ accountExternalId: company.id,
+ contactExternalId: email,
+ });
+
+ makeChurnZeroRequest(config, {
+ action: 'setAttribute',
+ entity: 'contact',
+ attr_FirstName: firstName,
+ attr_LastName: lastName,
+ attr_Email: email,
+ accountExternalId: company.id,
+ contactExternalId: email,
+ });
+ },
+ loaded: () => loaded,
+ };
+}
+
+function makeChurnZeroRequest({config, body}) {
+ return fetch(`https://${config.subdomain}.churnzero.net/i`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Cache-Control': 'no-cache',
+ },
+ body: JSON.stringify({
+ appKey: config.appKey,
+ ...body,
+ accountExternalId: body.accountExternalId || config.accountExternalId,
+ contactExternalId: body.contactExternalId || config.contactExternalId,
+ }),
+ });
+}
+
+export default churnZeroPlugin