Giter VIP home page Giter VIP logo

ember-metrics's Introduction

ember-metrics

Send data to multiple analytics services without re-implementing new API

Download count all time npm version Build Status Ember Observer Score

This addon adds a simple metrics service to your app that makes it simple to send data to multiple analytics services without having to implement a new API each time.

Using this addon, you can easily use bundled adapters for various analytics services, and one API to track events, page views, and more. When you decide to add another analytics service to your stack, all you need to do is add it to your configuration, and that's it!

Writing your own adapters for currently unsupported analytics services is easy too. If you'd like to then share it with the world, submit a pull request and we'll add it to the bundled adapters.

Currently supported services and options

  1. GoogleAnalytics

  2. GoogleAnalyticsFour

    • id: Measurement Id, e.g. G-XXXX
    • options: optional An object which will be directly passed to the configuration tag, e.g.:
    options = {
      anonymize_ip: true,
      debug_mode: environment === 'development',
    };

    By default GA4 automatically tracks page views when the history locations changes. This means that this.metrics.trackPage() is ignoreded by default. However, if you want to track the page views manually, you need to set send_page_view: false inside the options. To avoid double counting page views make sure enhanced measurement is configured correctly. Typically, this means disabling Page changes based on browser history events under the advanced settings of the page views section.

  3. Mixpanel

  4. GoogleTagManager

    • id: Container ID, e.g. GTM-XXXX

    • dataLayer: An array containing a single POJO of information, e.g.:

    dataLayer = [
      {
        pageCategory: 'signup',
        visitorType: 'high-value',
      },
    ];
    • envParams: A string with custom arguments for configuring GTM environments (Live, Dev, etc), e.g.:
    envParams: 'gtm_auth=xxxxx&gtm_preview=env-xx&gtm_cookies_win=x';
  5. Segment

  6. Piwik

  7. Intercom

  8. Facebook Pixel

    dataProcessingOptions: {
      method: ['LDU'],
      country: 1,
      state: 1000
    }
  9. Amplitude

  10. Azure App Insights

  11. Pendo

  12. MatomoTagManager

  13. Hotjar

Community adapters

  1. Adobe Dynamic Tag Management

  2. Simple Analytics

Installing The Addon

ember install ember-metrics

Compatibility

  • Ember.js v3.20 or above
  • Ember CLI v3.20 or above
  • Node.js v12 or above

Configuration

To setup, you should first configure the service through config/environment:

module.exports = function (environment) {
  var ENV = {
    metricsAdapters: [
      {
        name: 'GoogleAnalytics',
        environments: ['development', 'production'],
        config: {
          id: 'UA-XXXX-Y',
          // Use `analytics_debug.js` in development
          debug: environment === 'development',
          // Use verbose tracing of GA events
          trace: environment === 'development',
          // Ensure development env hits aren't sent to GA
          sendHitTask: environment !== 'development',
          // Specify Google Analytics plugins
          require: ['ecommerce'],
        },
      },
      {
        name: 'GoogleAnalyticsFour',
        environments: ['production'],
        config: {
          id: 'G-XXXX',
          options: {
            anonymize_ip: true,
            debug_mode: environment === 'development',
          },
        },
      },
      {
        name: 'Mixpanel',
        environments: ['production'],
        config: {
          token: '0f76c037-4d76-4fce-8a0f-a9a8f89d1453',
        },
      },
      {
        name: 'Segment',
        environments: ['production'],
        config: {
          key: '4fce-8a0f-a9a8f89d1453',
        },
      },
      {
        name: 'Piwik',
        environments: ['production'],
        config: {
          piwikUrl: 'http://piwik.my.com',
          siteId: 42,
        },
      },
      {
        name: 'Intercom',
        environments: ['production'],
        config: {
          appId: 'def1abc2',
        },
      },
      {
        name: 'FacebookPixel',
        environments: ['production'],
        config: {
          id: '1234567890',
          dataProcessingOptions: {
            method: ['LDU'],
            country: 1,
            state: 1000,
          },
        },
      },
      {
        name: 'Amplitude',
        environments: ['production'],
        config: {
          apiKey: '12345672daf5f3515f30f0000f1f0000cdfe433888',
          options: {
            trackingOptions: {
              ip_address: false,
            },
            // ...other amplitude configuration options
            // https://developers.amplitude.com/#sdk-advanced-settings
          },
        },
      },
      {
        name: 'AzureAppInsights',
        environments: ['production'],
        config: {
          instrumentationKey: '123',
          // ...other appInsights configuration options
          // https://github.com/microsoft/ApplicationInsights-JS#configuration
        },
      },
      {
        name: 'Pendo',
        environments: ['production'],
        config: {
          apiKey: '123456789',
        },
      },
      {
        name: 'LocalAdapter',
        environments: ['all'], // default
        config: {
          foo: 'bar',
        },
      },
      {
        name: 'MatomoTagManager',
        environments: ['production'],
        config: {
          matomoUrl: 'matomo.my.com',
          containerId: 'acd123',
        },
      },
      {
        name: 'Hotjar',
        environments: ['production'],
        config: {
          siteId: '123456789',
        },
      },
    ],
  };
};

Adapter names are PascalCased. Refer to the list of supported adapters above for more information.

The metricsAdapters option in ENV accepts an array of objects containing settings for each analytics service you want to use in your app in the following format:

/**
 * @param {String} name Adapter name
 * @param {Array} environments Environments that the adapter should be activated in
 * @param {Object} config Configuration options for the service
 */
{
  name: 'Analytics',
  environments: ['all'],
  config: {}
}

Values in the config portion of the object are dependent on the adapter. If you're writing your own adapter, you will be able to retrieve the options passed into it:

// Example adapter
export default class ExampleAdapter extends BaseAdapter {
  init() {
    const { apiKey, options } = this.config;
    this.setupService(apiKey);
    this.setOptions(options);
  }
}

To only activate adapters in specific environments, you can add an array of environment names to the config, as the environments key. Valid environments are:

  • development
  • test
  • production
  • all (default, will be activated in all environments)

Content Security Policy

If you're using ember-cli-content-security-policy, you'll need to modify the content security policy to allow loading of any remote scripts. In config/environment.js, add this to the ENV hash (modify as necessary):

// example for loading Google Analytics
contentSecurityPolicy: {
  'default-src': "'none'",
  'script-src': "'self' www.google-analytics.com",
  'font-src': "'self'",
  'connect-src': "'self' www.google-analytics.com",
  'img-src': "'self'",
  'style-src': "'self'",
  'media-src': "'self'"
}

Usage

In order to use the addon, you must first configure it, then inject it into any Object registered in the container that you wish to track. For example, you can call a trackPage event across all your analytics services whenever you transition into a route, like so:

// app/routes/application.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class ApplicationRoute extends Route {
  @service metrics;
  @service router;

  constructor() {
    super(...arguments);

    this.router.on('routeDidChange', () => {
      const page = this.router.currentURL;
      const title = this.router.currentRouteName || 'unknown';

      this.metrics.trackPage({ page, title });
    });
  }
}

If you wish to only call a single service, just specify it's name as the first argument:

// only invokes the `trackPage` method on the `GoogleAnalyticsAdapter`
metrics.trackPage('GoogleAnalytics', {
  title: 'My Awesome App',
});

Context

Often, you may want to include information like the current user's name with every event or page view that's tracked. Any properties that are set on metrics.context will be merged into options for every Service call.

this.metrics.context.userName = 'Jimbo';
this.metrics.trackPage({ page: 'page/1' }); // { userName: 'Jimbo', page: 'page/1' }

API

Service API

There are 4 main methods implemented by the service, with the same argument signature:

  • trackPage([analyticsName], options)

    This is commonly used by analytics services to track page views. Due to the way Single Page Applications implement routing, you will need to call this on the activate hook of each route to track all page views.

  • trackEvent([analyticsName], options)

    This is a general purpose method for tracking a named event in your application.

  • identify([analyticsName], options)

    For analytics services that have identification functionality.

  • alias([analyticsName], options)

    For services that implement it, this method notifies the analytics service that an anonymous user now has a unique identifier.

If an adapter implements specific methods you wish to call, then you can use invoke

  • invoke(method, [analyticsName], options)

    metrics.invoke('trackLink', 'Piwik', {
      url: 'my_favorite_link',
      linkType: 'download',
    });

Lazy Initialization

If your app implements dynamic API keys for various analytics integration, you can defer the initialization of the adapters. Instead of configuring ember-metrics through config/environment, you can call the following from any Object registered in the container:

// app/routes/application.js
import Route from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class ApplicationRoute extends Route {
  @service metrics;

  afterModel(model) {
    const id = model.googleAnalyticsKey;

    this.metrics.activateAdapters([
      {
        name: 'GoogleAnalytics',
        environments: ['all'],
        config: {
          id,
        },
      },
    ]);
  }
}

Because activateAdapters is idempotent, you can call it as many times as you'd like. However, it will not reinstantiate existing adapters.

Since ember-metrics now automatically removes all unused adapters, it's also important to force the inclusion of the adapter via config/environment. NOTE: If the adapter is already defined in the metricsAdapters array of config/environment then this step is not necessary.

// config/environment
module.exports = function(environment) {
  var ENV = {
    'ember-metrics': {
      includeAdapters: ['google-analytics']
    }
  };

  return ENV;

Writing Your Own Adapters

First, generate a new Metrics Adapter:

$ ember generate metrics-adapter foo-bar

This creates app/metrics-adapters/foo-bar.js and a unit test at tests/unit/metrics-adapters/foo-bar-test.js, which you should now customize.

Required Methods

The standard contracts are optionally defined, but init and willDestroy must be implemented by your adapter.

init

This method is called when an adapter is activated by the service. It is responsible for adding the required script tag used by the integration, and for initializing it.

willDestroy

When the adapter is destroyed, it should remove its script tag and property. This is usually defined on the window.

Usage

Once you have implemented your adapter, you can add it to your app's config, like so:

module.exports = function (environment) {
  var ENV = {
    metricsAdapters: [
      {
        name: 'MyAdapter',
        environments: ['all'],
        config: {
          secret: '29fJs90qnfEa',
          options: {
            foo: 'bar',
          },
        },
      },
    ],
  };
};

Contributors

We're grateful to these wonderful contributors who've contributed to ember-metrics:

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

ember-metrics's People

Contributors

cah-brian-gantzler avatar chrismllr avatar cibernox avatar cvx avatar dcyriller avatar denneralex avatar dependabot[bot] avatar gabrielcousin avatar gitatmax avatar greatwizard avatar homu avatar jelhan avatar jfdnc avatar jherdman avatar joepheijnen avatar josemarluedke avatar jrjohnson avatar kennstenicht avatar lfrost avatar locks avatar mike-north avatar nselikoff avatar opsb avatar poteto avatar reidab avatar sly7-7 avatar turbo87 avatar tyleryasaka avatar vincenthardouin avatar windvis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ember-metrics's Issues

throwing error when in development

When I have the config for mixpanel set to only do it in production when I'm in development and come across code that implements identify I'm getting an error in the console saying

Error while processing route: index.index Cannot read property 'identify' of undefined TypeError: Cannot read property 'identify' of undefined

And

TypeError: Cannot read property 'identify' of undefined

Fastboot-friendly Usage Tips

The suggested usage of this addon points users toward something that won't work with Fastboot

// app/router.js
import Ember from 'ember';
import config from './config/environment';

const Router = Ember.Router.extend({
  location: config.locationType,
  metrics: Ember.inject.service(),

  didTransition() {
    this._super(...arguments);
    this._trackPage();
  },

  _trackPage() {
    Ember.run.scheduleOnce('afterRender', this, () => {


     // THIS LINE REFERS TO A GLOBAL THAT DOESN'T EXIST IN FASTBOOT LAND
      const page = document.location.pathname;
     // THIS LINE REFERS TO A GLOBAL THAT DOESN'T EXIST IN FASTBOOT LAND


      const title = this.getWithDefault('currentRouteName', 'unknown');

      Ember.get(this, 'metrics').trackPage({ page, title });
    });
  }
});

Add support for Fastboot

I'm running into issues using ember-metrics with fastboot due to window being undefined. As I understand it, any use of browser globals need to be guarded. Working on a PR now that should solve it.

Accessing adapter's specific API

Using the Piwik service, I wanted to use its trackLink(url, linkType) function.

For now, it's possible, by implementing the trackLink function in the adapter, and calling it via metrics.invoke('trackLink', 'Piwik', { url: 'url', linkType: 'download' })

This seems obviously not possible to add each possible adapter function in the metrics api, so I wonder what could be done for such a case.

Maybe using invoke is just fine, and in that case, I will gladly open a PR to document it in the readme.

alias / identify function formats

Hello,

I'm wondering why is the function call designed, so that I have to call identify and alias and trackEvent in such a non-pretty form, when those function will always take 1 parameter (distinctId as a string)?

It would be much nicer to do:
Ember.get(this, 'metrics').alias(distinct_id); // distinct_id must always be there

instead of
Ember.get(this, 'metrics').alias({ distinctId: distinct_id});

If there's a chance that a hash of options can be passed to a function, it should be the second argument.

The same goes with identify and trackEvent (which always takes at least event name).

The adapter generator does not include a willDestroy method.

According to the README, the willDestroy method is required but when generating a new adapter the method is not included in the stub.

$ ember generate metrics-adapter foo-bar
import BaseAdapter from 'ember-metrics/metrics-adapters/base';

export default BaseAdapter.extend({
  toStringExtension() {
    return 'foo-bar';
  },

  init() {

  },

  identify() {

  },

  trackEvent() {

  },

  trackPage() {

  },

  alias() {

  }
});

Is `activate` the right place to call `trackPage`?

Due to the way Single Page Applications implement routing, you will need to call this on the activate hook of each route to track all page views.

Is activate really the best place to call this? what if I'm moving between pages on the same route (i.e. multiple products). activate only runs the first time the route is entered, and not between model changes.

Should the Docs instead suggest this be be called in a didTransition action?

Intercom adapter

We use Intercom in our app and we're currently adding it to a custom ember-metrics adapter. Would be happy to create a PR if you'd consider adding Intercom support to ember-metrics core?

Pass in a hash of integrations instead of a string to the service

e.g.

metrics.trackEvent({
  integrations: {
    GoogleAnalytics: true,
    Mixpanel: false,
    'customer.io': true
  },
  event: 'foo',
  action: 'bar'
});

Potential issues:

  • What if I want to send a property to the analytics service that is called integrations?
    • possible solutions – prefix integrations, pass in 2 objects as args

I've created an adapter addon for Chameleon

I've just created today this addon: https://github.com/cibernox/ember-metrics-chameleon-adapter

It's basically code that I wrote ~6m ago, but now I happen to need in two projects and I decided to extract it into an addon.

Chameleon is not exactly a tracking library, but the similarities are enough to make ember-metrics somehow useful and a good abstraction around any library that that you want to lazy-initialize from an external script to then identify/trackEvents with it.

If you even want to merge this adapter into the default set of adapter just let me know and I'll be happy to PR those changes here.

Example of Google Tag Manager

Could you please provide an example of how to use Google TagManager with the dataLayer property being populated.

It would be really appreciated.

Thank you.

Debug State

It would be nice if there were a way to turn on debug logging when implementing events in ember metrics. For instance, instead of tracking events with google analytics, it logs some info in the console about what would be sent up to GA.

Support ember under 1.13

Since Ember.LinkComponent is not present in older versions it throws error when trying to use/initialize the addon.

Maybe it should fallback to Ember.LinkView when LinkComponent is not present.

I'm using:
ember: 1.12.0
ember-cli: 0.2.7

Proposal: expose metrics.context for properties that should be included with every event

Most apps have certain pieces of context that should be included with every pageView or event e.g. currentUser.name, currentTenant.name.

I'd like to propose that we expose metrics.context. Anything that's bound to this context would be merged into the options e.g.

export default Ember.Route.extend({
    setupController(controller, model) {
        var currentTenant = model;
        this.set('metrics.context.tenantName', currentTenant.name);
    }
});

metrics.trackEvent({event: 'demo_requested'}); 
// => {event: 'demo_requested', tenantName: "name of current tenant"};

I'm currently adding it to an app by wrapping the metrics service with another analytics service that does the same thing but it occurred to me that it might be a useful feature to include in the library. If people are keen I'll put a PR together.

Add support for environments to Google Tag Manager adapter

Google Tag Manager has support for different environments. This could be useful for publishing different versions of containers to production vs a staging environment. In order to consume these different containers there are additional query params on the script tag for gtm.js:

  • gtm_auth
  • gtm_preview
  • gtm_cookies_win

I've implemented a local version of the gtm adapter supporting this, and I'd be happy to PR it to the official adapter if there's interest.

TypeError: Cannot read property 'trackEvent' of undefined

I'm getting below error :
ember.debug.js:29169 Uncaught TypeError: Cannot read property 'trackEvent' of undefined

The Output of requirejs.entries is below

screenshot from 2016-11-15 11 56 53

config/environment.js

`
module.exports = function(environment) {
var ENV = {
metricsAdapters: [
{
name: 'Mixpanel',
environments: ['all'],
config: {
token: 'mixpanel_token'
}
}
],
....

....
}
}

`

Add below code in my controller

`
import Ember from 'ember';
import config from './config/environment';

....
....

Ember.get(this, 'metrics').trackEvent('Mixpanel', {
title: 'New Event'
});

....
.....
`

Please look into this. I'm using "ember-cli": "1.13.8" version

Depreciation in Ember 2.1

In 2.1 a deprecation was added:

DEPRECATION: The initialize method for Application initializer 'metrics' should take only one argument - App, an instance of an Application. [deprecation id: ember-application.app-initializer-initialize-arguments] See http://emberjs.com/deprecations/v2.x/#toc_initializer-arity for more details.

If I get a chance later, I'll try to create a PR to fix this. But if someone else has time to do it sooner, that'd be great.

Filter adapters on build tree according to environment options

Today all the adapters on metrics-adapters folder are included in the build tree even if on the config there's only one selected, e.g. if on the environment there's only GoogleAnalytics setup Mixpanel and others are included as well on the vendor.js script.
A better approach would be to filter the files on the build process to include only the ones declared on environment + base.js.

This could be done on the treeForAddon hook in the index.js file, excluding from the broccoli tree the adapters that are not on environment, keeping only necessary adapters + base.js. Would be even better if the base.js file was not on the same folder so the filter doesn't have to care about it.

Let me know your thoughts.

Error running ember test and ember server

Hi! I'm new to ember, so this could be something on my end, but I've followed the installation and configuration steps in the README, and am getting an error when running ember test and ember server.

Environment:

> ember -v
version: 0.2.3
node: 0.12.12
npm: 2.7.6

Changes:

> git diff
diff --git a/config/environment.js b/config/environment.js
index e928b12..647d58c 100644
--- a/config/environment.js
+++ b/config/environment.js
@@ -16,7 +16,17 @@ module.exports = function(environment) {
-    }
+    },
+
+    metricsAdapters: [
+      {
+        name: 'Mixpanel',
+        environments: ['development'],
+        config: {
+          token: 'XXXXXXXXXXXXXXXXXXXXXXXXXX'
+        }
+      }
+    ]
   };                                                                                                                                                                                                                           

diff --git a/package.json b/package.json
index df63ba3..3c53236 100644
--- a/package.json
+++ b/package.json
@@ -40,6 +40,7 @@
     "ember-data": "1.0.0-beta.16.1",
     "ember-drag-drop": "^0.1.4",
     "ember-export-application-global": "^1.0.0",
+    "ember-metrics": "0.6.0",
     "ember-select-2": "1.2.0",
     "ember-template-compiler": "^1.9.0-alpha",
     "ember-validations": "^2.0.0-alpha.3",

Error when running tests:

> ember test
ember test
version: 0.2.3

A new version of ember-cli is available (2.4.2). To install it, type ember update.
Invalid watchman found, version: [4.4.0] did not satisfy [^3.0.0], falling back to NodeWatcher.
Visit http://www.ember-cli.com/#watchman for more info.
Build failed.
File: frontend/initializers/metrics.js
Line 5: Unexpected token =
Error: Line 5: Unexpected token =
    at throwError (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2692:21)
    at throwUnexpected (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2754:9)
    at expect (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2763:13)
    at parseObjectInitialiser (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:3303:17)
    at parseVariableDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4650:18)
    at parseVariableDeclarationList (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4690:23)
    at parseConstLetDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4721:24)
    at parseSourceElement (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:6267:24)
    at parseFunctionSourceElements (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:5603:29)
    at parseFunctionDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:5800:16)

Running ember server yields the same error:

> ember server
version: 0.2.3

A new version of ember-cli is available (2.4.2). To install it, type ember update.
Invalid watchman found, version: [4.4.0] did not satisfy [^3.0.0], falling back to NodeWatcher.
Visit http://www.ember-cli.com/#watchman for more info.
Livereload server on port 35729
Serving on http://localhost:4200/
File: frontend/initializers/metrics.js
Line 5: Unexpected token =
Error: Line 5: Unexpected token =
    at throwError (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2692:21)
    at throwUnexpected (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2754:9)
    at expect (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:2763:13)
    at parseObjectInitialiser (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:3303:17)
    at parseVariableDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4650:18)
    at parseVariableDeclarationList (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4690:23)
    at parseConstLetDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:4721:24)
    at parseSourceElement (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:6267:24)
    at parseFunctionSourceElements (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:5603:29)
    at parseFunctionDeclaration (/Users/bploetz/frontend/node_modules/ember-cli/node_modules/broccoli-es3-safe-recast/node_modules/es3-safe-recast/node_modules/recast/node_modules/esprima-fb/esprima.js:5800:16)

Even if I remove the metricsAdapters from config/environment.js, the problem persists, so it seems as though simply having the ember-metrics dependency causes this.

Any ideas?

option `hitCallback` doesn't work for google analytics.

I'm trying to track outbound link navigations, and found that the way to do this with google analytics is to send an event and in the options set a hitCallback key to a function that will be called when the event has been received. This just flat out doesn't seem to work.. here's my component.js:

function exitToMessenger() {
  console.log('redirecting to messenger.com!!')
  window.location.href = 'https://www.messenger.com/t/heyimlea';
}

export default Ember.Component.extend({
  metrics: Ember.inject.service(),
  actions: {
    sendToMessenger() {
      console.log('send to messenger called')
      var metrics = Ember.get(this, 'metrics')

      var eventData = {
        hitType: 'event',
        eventCategory: 'Outbound Link',
        eventAction: 'click',
        eventLabel: 'Sent to messenger!',
        eventValue: 'https://www.messenger.com/t/heyimlea'
      };

      // if (navigator.sendBeacon) {
      //   //https://github.com/googleanalytics/autotrack/blob/bcdd409c22430553a2a43275386877bf37600e68/lib/plugins/outbound-form-tracker.js#L77
      //   //https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
      //   eventData.transport = 'beacon'
      //   metrics.trackEvent(eventData)
      //   //metrics.trackPage({page: '/sent2messenger', title: "exiting to messenger" });
      //   //be sure analytics.js calls sendBeacon before exiting
      //   setTimeout(exitToMessenger, 4)
      // } else {
        eventData.hitCallback = exitToMessenger;
        metrics.trackEvent(eventData)
      // }
    }
  }

Searching something along the lines of 'analytics track outbound link' I find this help article from google analytics suggesting this method: https://support.google.com/analytics/answer/1136920?hl=en
Here's the docs on hitCallback: https://developers.google.com/analytics/devguides/collection/analyticsjs/sending-hits#hitcallback

I'd love to get this fixed and tested asap so that the ember community can have one comprehensive addon for analytics

Issues when running `ember test`

We're currently experiencing an error when running ember test in our app:

Attempting to inject an unknown injection: `service:metrics`

We currently have over ~150 failing tests due to this issue.

If we add the following, the test passes:

moduleForComponent('box-tabs', {
+  needs: ['service:metrics']
});

Is the right approach to add in the needs in all ~150 failing tests, or, is there a better solution?

[QUESTION] Test extended built-in adapters

I cleanup my own Piwik adapter using the built-in one. I just have some customization for the adapter (like sending custom dimensions).

I have define a app/metrics-adapters/piwik.js, like this:

import PiwikAdapter from 'ember-metrics/metrics-adapters/piwik';

export default PiwikAdapter.extend({
  identify(options = {}) {
    this._super(...arguments);
    window._paq.push(['setCustomDimension', 1, options.organizationName]);
    window._paq.push(['setCustomDimension', 2, options.userId]);
  }
});

So far, so good, but when I wanted to test it, I can"t find a way to resolve ember-metrics/metrics-adapters/piwik.

In the needs property of my unit test, I tried to add a reference to ember-metrics@metrics-adapter:piwik with no success, I encounter this error: Attempting to register an unknown factory: 'ember-metrics@metrics-adapter:piwik'.
When referencing ember-metrics@metrics-adapter:base, it seems like the BaseAdapter is beeing correctly resolved.

So my question: How can I test an extended adapter ?

No-op for disabled services

Right now if I have a service configured for production only or don't have an API key present it throws a javascript error when I try to call functions on the metrics service. It would be super if it just resulted in a no-op instead so I wouldn't have to have all these guards in my code for its presence.

Use set prior to send?

I wonder if in the GA adapter, set shouldn't be used to update the tracker prior to send. The documentation indicates:

While technically the send command for pageview hits accepts an optional page field as the third parameter, passing the page field that way is not recommend when tracking single page applications. This is because fields passed via the send command are not set on the tracker—they apply to the current hit only. Not updating the tracker will cause problems if your application sends any non-pageview hits (e.g. events or social interactions), as those hits will be associated with whatever page value the tracker had when it was created.

https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications#tracking_virtual_pageviews

I'm not sure if how the way the adapter currently works (sending object to send with hitType) will address this, so thought I'd open this issue.

contentSecurityPolicy img-src

I believe that in the readme you forgot to include google 1x1 image, namely:

contentSecurityPolicy: {
    'img-src':     ["'self' www.google-analytics.com"]
}

getting Cannot read property 'alias' of undefined

Hello,

I'm having issues when calling the alias function (I'm using Mixpanel and GoogleTagManager adapter) from a unauthenticatedRouteMixin mixin that I use for my app routes. It looks like Ember.get(this, 'metrics') is undefined.

The error occurres when I do:

const metrics = Ember.get(this, 'metrics');
metrics.alias(distinct_id);

Here's my configuration:

    metricsAdapters: [
      {
        name: 'GoogleTagManager',
        environments: ['development', 'production'],
        config: {
          id: 'GTM-KKHS44'
        }
      },
      {
        name: 'Mixpanel',
        environments: ['development', 'production'],
        config: {
          token: 'bcb8f05d6f6fbac46a206227b4ec7'
        }
      }
    ],

The other methods - identify, trackEvent and trackPage seems to be working fine..

Why is that?

Thanks

Content security policy not solved

mixpanel-2-latest.min.js:64 [Report Only] Refused to connect to 'http://api.mixpanel.com/track/?data=eyJldmVudCI6ICJwYWdlIHZpZXdlZCIsInByb3B…TJkODdlNDBiODZhNGRmMWQ1ZGRhYjg0NCIsIiRfX2MiOiAwfX0%3D&ip=1&_=1470169823818' because it violates the following Content Security Policy directive: "connect-src 'self' 'unsafe-inline' http://*.pubnub.com https://*.pubnub.com https://auth.firebase.com https://api.mixpanel.com wss://*.firebaseio.com wss://*.remoto.me:* http://*.remoto.me:* ws://*.remoto.me:* https://*.remoto.me:* ws://localhost:49152 ws://0.0.0.0:49152 http://undefined:4200/csp-report".

I have this error, but i already put mixpanel in content security policy in my environment.js

contentSecurityPolicy: {
  'default-src': "'none'",
  'script-src': "'self' https://api.mixpanel.com",
  'font-src': "'self'",
  'connect-src': "'self' https://api.mixpanel.com",
  'img-src': "'self'",
  'style-src': "'self'",
  'media-src': "'self'"
}

Support for Piwik

I would be very interested in contributing tracking for Piwik. Would that be something you are interested in?

Reinitialize Adapters for Different Pods

We have a rather large app with a bunch of different pods under. Right now, I can pass the info in using lazy loading but only the info from the first loaded pod is used. Sounds crazy, right? (We're using Segment for this example)

Why would you do something like that you ask?

Because it would allow us to treat our pods like separate apps all living under the same umbrella with different and distinct tracking information. I'd really hate to have to split all our code into separate apps just to get the tracking info working as described.

I think it would be awesome if I could use the lazy loading technique to override an adapter instance with a new key when loading into a route.

Do you have any suggestions on how to accomplish this?

Not recognizing passed in services

I'm having issues specifying the specific services I want to use. Not sure what the correct syntax is but I've tried all combinations specified in the readme. An example of what I've tried:

this.get('metrics').trackEvent(['Mixpanel', 'Segment'], { event: "Event example" });

Could not find metrics adapter GoogleAnalytics

I'm attempting to add ember-metrics to my Ember project, starting with Google Analytics.

I've set my app/router.js and config/environment.js as per this projects README:

config/environment.js

var ENV = {
...
    metricsAdapters: [
      {
        name: 'GoogleAnalytics',
        environments: ['all'],
        config: {
          id: 'UA-XXXX-Y'
        }
      }
    ],
...
}

app/router.js

import Ember from 'ember';
import config from './config/environment';

const Router = Ember.Router.extend({
  location: config.locationType,
  metrics: Ember.inject.service(),

  didTransition() {
    this._super();
    this._trackPage();
  },

  _trackPage() {
    Ember.run.scheduleOnce('afterRender', this, () => {
      const page = document.location.pathname;
      const title = this.getWithDefault('currentRouteName', 'unknown');

      Ember.get(this, 'metrics').trackPage({ page, title });
    });
  }
});

export default Router;

However I don't see the GA code snippet being inserted into my compiled JS, and I am getting the following error in my dev console

Uncaught Error: Assertion Failed: [ember-metrics] Could not find metrics adapter GoogleAnalytics.assert @ ember.debug.js:6254assert @ ember.debug.js:16075_activateAdapter @ metrics.js:223(anonymous function) @ metrics.js:148activateAdapters @ metrics.js:145init @ metrics.js:90superWrapper @ ember.debug.js:22633Class @ ember.debug.js:36144ClassMixinProps.create @ ember.debug.js:36422instantiate @ ember.debug.js:1511lookup @ ember.debug.js:1361Container.lookup @ ember.debug.js:1291(anonymous function) @ ember.debug.js:32719injectedPropertyGet @ ember.debug.js:16861ComputedPropertyPrototype.get @ ember.debug.js:14893get @ ember.debug.js:20290(anonymous function) @ router.js:19Queue.invoke @ ember.debug.js:327Queue.flush @ ember.debug.js:391DeferredActionQueues.flush @ ember.debug.js:192Backburner.end @ ember.debug.js:570Backburner.run @ ember.debug.js:692Backburner.join @ ember.debug.js:712run.join @ ember.debug.js:20709(anonymous function) @ ember.debug.js:20772fire @ jquery.js:3099self.fireWith @ jquery.js:3211jQuery.extend.ready @ jquery.js:3417completed @ jquery.js:3433```

Is there something I'm missing?

Event Example

Having a bit of trouble calling a track event from a controller. Not too sure if I've found a bug or I'm just doing it wrong. Can someone post an example?

TypeError: Cannot read property 'identify' of undefined

Hello,

I'm getting the "Cannot read property" error when I try to run the following code:

    @get('metrics').identify('Mixpanel', {
      distinctId: '[email protected]'
    })

The error is coming from metrics.js line 130:
https://github.com/poteto/ember-metrics/blob/master/addon/services/metrics.js#L130

This code has been running fine in my 'production' environment. When I recently added a 'localhost' environment is when I got the error.

My config/environment.js looks like this:

  if (environment === 'localhost') {
      ENV.apiHost = 'http://localhost';
      ENV.apiURL = 'http://localhost'
      ENV.metricsAdapters = [{
          name: 'Mixpanel',
          environments: ['development'],
          config: { token: 'xxxxx' },
          includeAdapters: ['mixpanel']
      }, ]
  }
  if (environment === 'production') {
    ENV.apiHost = 'https://my-domain.com';
    ENV.apiURL = 'https://my-domain.com';
    ENV.metricsAdapters = [
      {
        name: 'Mixpanel',
        environments: ['production'],
        config:{ token: 'xxxxx' },
        includeAdapters: ['mixpanel']
      },
    ]
  }

Is there something weird because I have this 'localhost' env?

Any help is appreciated! Thanks!

Version bump / facebook pixel adapter

A "facebook pixel" adapter has been added about a month ago. It is very confusing to read about it on README.md file a then find out it is not available on latest release (version 0.7.0).

What are contributing rules in such situations? What do you think about releasing more often?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.