Code Monkey home page Code Monkey logo

angular-segment-analytics's Introduction

ngSegment: Segment analytics for AngularJS

Build Status Coverage Status Dependencies Status License

A highly configurable module for easily adding Segment analytics to any Angular app. Like the project? Star it!

Table of Contents

Get Started

  1. Download the ngSegment source from Bower, npm, or Github.
  2. Include segment.min.js in your index.html, after including Angular.
  3. Add 'ngSegment' to your main module's list of dependencies: angular.module('myApp', ['ngSegment']);.

Bower: bower install angular-segment-analytics --save

npm: npm install angular-segment-analytics

Usage

Set your API key using either of the configuration methods provided (provider or constant), and you're ready to start using Segment in your app.

// analytics.js will be asynchronously auto-loaded
segmentProvider.setKey('abc');

Most Segment methods (see Analytics.js) are available on the segment service created by ngSegment.

segment.track('event', { prop: 'value' });

Continue reading about the configuration options, or jump to the Examples.

Configuration

ngSegment provides two configuration mechanisms: using a provider or constant. These options are available so you can pick the mechanism that fits your application best.

It is not recommended to mix configuration mechanisms, but if you do configuration via constant will take precedence.

Provider

The segmentProvider is available during your application's .config() phase, before services have been instantiated. Read the AngularJS documentation to learn more about module configuration blocks.

angular.module('myApp').config(function (segmentProvider) {
    segmentProvider
        .setKey('abc')
        .setCondition(function ($rootScope) {
            return $rootScope.isProduction;
        })
        .setDebug(true)
});

All of the analytics.js methods are also available on both the segmentProvider and segment service. You might want to call .identify() during your app's config block if you have your user's information available at that time:

segmentProvider.identify('user-id', {});

Constant

You can also set any of the configuration options available by providing your own segmentConfig constant. You only need to register your constant with your own app using angular.module('myApp').constant('segmentConfig', {});, and the segmentProvider will find it.

Your segmentConfig constant should overwrite the properties found in segmentDefaultConfig. Any properties not overridden will default to the values found in that file.

angular.module('myApp').constant('segmentConfig', {

  // These values will automatically be loaded by the segment service
  apiKey: 'abc',
  condition: function ($rootScope) {
      return $rootScope.isProduction;
  }
});

Read more about AngularJS constants.

API Documentation

The configuration API is available on the segmentProvider. For configuring via a constant, see segmentDefaultConfig for the property names to override.

All configuration methods are chainable:

segmentProvider
    .setKey('xx')
    .setAutoload(false)
    .setDebug(true);

setKey(string)

Sets the API key (or Write Key) from your Segment project, found in the setup guide or settings for your project. Your API key is required before Analytics.js can be loaded.

Note: If you don't set the API key during the .config() phase of your app (using either the provider or constant forms of configuration), then ngSegment will not be able to autoload Analytics.js and you'll need to load it manually using segmentLoader.load(apiKey);.

setCondition(injectable callback)

Default: none

// Disable tracking for non-production environments
segmentProvider.setCondition(function ($rootScope) {
    return !$rootScope.environment.isProduction;
});

The callback function is also injected with the analytics.js method name and parameters being called.

// Disble tracking for admin users
segmentProvider.setCondition(function ($rootScope, method, params) {
    if (!(method === 'track' and $rootScope.user.isAdmin)) {
        return true;
    }
});

setAutoload(boolean)

Default: true

ngSegment autoloads Segment's Analytics.js before the AngularJS .run() phase if an API key has been set. Set autoload to false if you already include analytics.js in your build script.

If you need to load the Segment analytics.js script on-demand, you can use the segmentLoader or segmentLoaderProvider:

angular.module('myApp').controller('MyController', function (segmentLoader) {
    segmentLoader.load('abc');
});

If you already set the API key via configuration, you can access it using the segment service:

angular.module('myApp').controller('MyController', function (segmentLoader) {
    segmentLoader.load(segment.config.apiKey);
});

or via provider in your application's config() block:

angular.module('myApp').config(function (segmentLoaderProvider) {
    segmentLoaderProvider.load('abc');
});

setLoadDelay(integer)

Default: 0ms (no delay)

Used in combination with setAutoload, this controls the amount of time in milliseconds ngSegment will wait before autoloading Segment's Analytics.js.

Why: If your app loads many resources on page load or asynchronously, and your app doesn't require Segment in the first few seconds of application use, then it could be beneficial to defer loading Segment until other required resources have loaded (scripts, css, fonts, images, etc). Depending on the integrations you've enabled, Segment itself will load a series of additional scripts (e.g. Google Analytics, Intercom). Most browsers limit max connections (across multiple host names) to 17 connections at a time. If you don't hit this limit by the time Analytics.js is autoloaded, then you won't see any benefit from delaying. Note: any events tracked using ngSegment before Analytics.js has loaded will be queued and replayed once Analytics.js has been loaded. If the user leaves or reloads the page before this, then the events will be lost.

If you're using the segmentLoader to manually load Analytics.js and still want to introduce a load delay, then instead of setLoadDelay you can pass in a delay in milliseconds as the second parameter to .load():

angular.module('myApp').controller('MyController', function (segmentLoader) {

    // Delay loading Analytics.js for 3 seconds
    segmentLoader.load(segment.config.apiKey, 3000);
});

setEvents(object)

Default: none

Stores an object on the segment service for easy reference later using segment.events.

Why: if your app tracks many unique events, it will quickly become unwieldy to keep track of event names if they're hard-coded in your code each time you call segment.track('Event Name', eventData). For better organization, you may want to create an Angular constant to store all events your app uses by name. You can store this constant on the segment service so you don't need to inject your event names constant into every controller/service/etc that uses segment.

angular.module('myApp').constant('SegmentEvents', {
    SIGNED_UP: 'Signed Up'
});

angular.module('myApp').config(function (segmentProvider, SegmentEvents) {

    // EventsConstant is a key-value object of events you track
    segmentProvider.setEvents(SegmentEvents);
});

angular.module('myApp').controller('MyController', function (segment) {

    // Easy constant reference later
    segment.track(segment.events.SIGNED_UP, { plan: 'Startup' });
});

setDebug(boolean)

Default: false

Enables debug log statements that are helpful for troubleshooting or when first setting up Segment and ngSegment.

setConfig(object)

Convenience method for setting multiple config properties at once using an object that matches the property names of segmentDefaultConfig.

angular.module('myApp').config(function (segmentProvider) {

    // Set multiple config properties at once
    segmentProvider.setConfig({
        debug: true,
        apiKey: 'abc',
        autoload: false
    });
});

Examples

The segment service and segmentProvider implement most methods from Analytics.js. Check segmentDefaultConfig.methods for a complete list.

Page tracking

$rootScope.$on('$routeChangeSuccess', function () {
    segment.page();
});

Event tracking

$scope.myAction = function () {
  segment.track();
});

๐Ÿš€ Segment Angular Quickstart

Interested in writing analytics code once? With Segment, you can collect customer data from any source (web, mobile, server, CRM, etc.) and send it to over 250+ destinations (Google Analytics, Amplitude, Mixpanel, etc.) via the Segment dashboard. Follow the tailored guide for Angular to get setup.

angular-segment-analytics's People

Contributors

aleross avatar stwiname avatar williamgrosset 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

Watchers

 avatar  avatar

angular-segment-analytics's Issues

Instantiating a provider, error. segmentProvider not being recognized

Hi folks,
just trying to get started and get an error in my configuring angular-segment. The error I get is

Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module SegmentConfigProvider due to:
Error: [$injector:unpr] Unknown provider: segmentProvider

this is my code

angular.module('SegmentConfigProvider', []).config(function (segmentProvider) {
    segmentProvider
        .setKey('xxxxxxxxxxx')
        .setCondition(function ($rootScope) {
            return $rootScope.isProduction;
        })
        .setDebug(true)
});

if i omit the empty params passed to my SegmentConfigProvider I get an error that it failed to load and was mispelled.

Uncaught Error: [$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module SegmentConfigProvider due to:
Error: [$injector:nomod] Module 'SegmentConfigProvider' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.

Unable to use condition with minification

I'm getting injector errors when trying to set the condition.
What I have is;

condition: ($rootScope) => {
  return $rootScope.isProduction;
}

But when it gets minified $rootScope gets replaced with some arbitrary character. This causes Angular to have injector problems.

It would be nice if we could rely on stricter Angular DI.
Being able to do this would be nice:

condition: ['$rootScope', ($rootScope) => {
 return $rootScope.isProduction;
}]

But that then throws Condition callback must be a function

env variables

Hi, I'm happy user of you plugin, I love it! It helps a lot;)

What do you use (or how) to set environment variables? I noticed you use in code $rootScope.isProduction what looks nice a clean. Is some kind of plugin to grunt/gulp?

Is it possible to disable/modify default analytics.page() on page load?

I am attempting to use this module on static pages. Each static page must configure my application angular module. During this configuration I am configuring Segment using segmentProvider. I'm noticing that analytics.page() appears to be called each time a new page is loaded.

Is is possible to disable this?

Including module in karma test

Hi, I'm having some issue after I've included this module in my app, this broke my Karma tests.

The error: 'undefined' is not a function (evaluating 'function(a){this.validate(a)}.bind(this)')

My app runs without issue, so I guess that maybe is something with the karma config, but without this module everything is working fine (tests included). Did you have the same issue?

Thanks.

Error: Attempting to load Segment twice for Karma Jasmine Tests

I'm trying to include route change tracking for UI-Router events in the run() method, like below:

  angular
    .module('enterprise')
    .run(onRun);

  function onRun($rootScope, segment) {
    var deregistrationCallback = $rootScope.$on('$stateChangeSuccess', function() {
        segment.page();   
    });

    $rootScope.$on('$destroy', deregistrationCallback);
  }

However, my karma jasmine tests are throwing these errors:

PhantomJS 1.9.8 (Mac OS X 0.0.0) service: trackingService tests
        Error: Attempting to load Segment twice.

wrapper does not define SNIPPET_VERSION: Segment falls back to automatic initial page view

Segment started versioning its snippet. Right now it's 3.1.0 according to https://segment.com/docs/sources/website/analytics.js/quickstart/

What's important is that they moved the initial page view tracking from the analytics.js to the snippet.
But if there's no SNIPPET_VERSION they fall back to the old behaviour.

I noticed that I'm tracking initial page view twice in my angular 1.5 app where I call segment.page() in $stateChangeSuccess handler.

I reviewed the code that loads analytics.js and I saw no major differences.
@aleross can you review the code as well and verify it's safe to just add analytics.SNIPPET_VERSION = '3.1.0'?

Does this support intercomm's support feature?

When calling the identify function, segment's integration with intercom's support, will load the chat widget. However, while my identify and page functions are firing, I still see no chat widget.

this.init is not a function line 220

Hello I'm try to use your component but I got an error in the SegmentProvider.

It give me this error:

[$injector:modulerr] Failed to instantiate module app due to:
Error: [$injector:modulerr] Failed to instantiate module app.core due to:
Error: [$injector:modulerr] Failed to instantiate module ngSegment due to:
TypeError: this.init is not a function

I don't understand why the init function is not available.
Thank You

Change "latest" angular dependency to avoid shrinkwrap issues

Hi!

In your package.json, you specify the angular dependency with the version of latest. Using the latest version has proven to be problematic because it doesn't seem like npm and the shrinkwrap file can handle resolving the dependencies correctly.

Here are a few issues that explain the issue in a bit more detail:

It also might make more sense to make angular a peer dependency instead of a normal dependency. That way, users of your module are required to also have angular listed as a dependency, but it doesn't lock down the version as harshly as a normal dependency. You can just specify 1.x.x or >= 1.2.0 or whatever minimum requirements you have.

I'd be happy to submit a PR if you let me know how you want to resolve the issue! Thanks for the great work!

[PR discussion] Compatibility with browserify and webpack

In order to make this work with webpack or browserify-powered apps I needed to change the "main" to index.js in package.json and create an index.js file with:

require('./segment');
module.exports = 'ngSegment';

This practice is used in many other angular packages, but I'm not sure it is safe to apply to this project. What do you think?

Allow setting logger function

I have 2 use cases where this might be useful:

  1. when one wants to check WHERE segment.track was used one should use console.trace instead of console.log. Right now in debug mode all logs originate in the same line in angular-segment-analytics source which is not useful for finding a call with incorrect arguments)

  2. when one wanted to use different logger than console (for example $log)

Suggested API:

  • if setDebug() is called with a boolean then console.log is used, if function is passed this function is used, or
  • setLogger(someFunction)

Error when installing with bower

{
  "name": "xyz",
  "description": "",
  "main": "",
  "authors": [
  ],
  "license": "",
  "homepage": "",
  "private": true,
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "public/scripts",
    "test",
    "tests"
  ],
  "dependencies": {
    "angular-segment-analytics": "^1.2.0"
  }
}
node_modules/bower/bin/bower install
bower angular-segment-analytics#^1.2.0     invalid-meta The "main" field cannot contain minified files

https://github.com/bower/spec/blob/master/json.md#main

Do not include minified files.

Please add the reset function

Hi,
Thank you for your plugin!
Can you please add the reset() function in order to use it when my use logging out ? It would be very useful for anyone I guess!
Thank you in advance

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.