Veyo Technology: Using Angular Environments to Configure Multiple Segment Sources

March 1, 2018

Using Angular Environments to Configure Multiple Segment Sources

NOTE: This is part 2 of a series on tracking analytic events in Angular projects using Segment. You can find the first part on the Veyo Tech Blog. The code will be referenced in this article

Although code snippets are included in this article, you can find the full example application on GitHub.

Segment’s default setup provides you with a stupid-simple flow to get user events into your analysis tools. This is great for a simple production app where you have a single stream of data, such as a static sign up form which shows you how users interact with the fields you’ve deemed as important for your business. Unfortunately, the real world requires a higher level of interactions than a single stream of data can provide.

This is where Segment’s multiple sources feature comes to the rescue. A complex application will generate different types of analytic data – think UX events, error logging, query status logs, A/B tests, etc. You may use different services to generate data, which Segment views as a new source.

You also want to make sure that your development and test environments aren’t polluting your production data. Maybe it’s important to separate your data between internal and external users, or regions; again, individual sources give you the power to easily organize these use cases.

AngularCLI Environment Config

Luckily, AngularCLI is perfectly setup to configure multiple Segment sources through through its environment configuration.

An AngularCLI project has a directory for setting  environment specific variables. You tell it which environment to use by passing the `env` property, such as `ng serve –env=test` or `ng build –env=test`. However, before you can pass in the specific variable, you need to tell AngularCLI that they exist:

  1. Create a new environment file. For this example, let’s create an analytics environment:

[pastacode lang=”javascript” manual=”touch%20src%2Fapp%2Fenvironments%2Fenvironment.analytics.ts” message=”” highlight=”” provider=”manual”/]

We’re going to leave this file blank for now.

  1. Add the environment to our cli config

In `/.angular-cli.json`, add a new line to the `environments` list:

[pastacode lang=”javascript” manual=”%22environments%22%3A%20%7B%0A%22analytics%22%3A%20%22environments%2Fenvironment.analytics.ts%22%2C%0A%22dev%22%3A%20%22environments%2Fenvironment.ts%22%2C%0A%22prod%22%3A%20%22environments%2Fenvironment.prod.ts%22%0A%7D” message=”” highlight=”” provider=”manual”/]

  1. Now that we have multiple environments, it’s important that our environment variables are strongly typed. If you don’t have one already, you’llneed to make an environment interface:

[pastacode lang=”javascript” manual=”touch%20src%2Fapp%2Fenvironments%2Fenvironment.model.ts” message=”” highlight=”” provider=”manual”/]

This file will export our interface. We don’t have much right now, but we do have the `production` variable, so we can model that:

[pastacode lang=”javascript” manual=”export%20interface%20Environment%20%7B%0Aproduction%3A%20boolean%3B%0A%7D” message=”” highlight=”” provider=”manual”/]

  1. The other environment configurations need to use the interface:

[pastacode lang=”javascript” manual=”import%20%7B%20Environment%20%7D%20from%20′.%2Fenvironment.model’%0A%0Aexport%20const%20environment%3A%20Environment%20%3D%20%7B%0Aproduction%3A%20false%0A%7D%3B” message=”src/environments/environment.ts” highlight=”” provider=”manual”/]

[pastacode lang=”javascript” manual=”import%20%7B%20Environment%20%7D%20from%20′.%2Fenvironment.model’%0A%0Aexport%20const%20environment%3A%20Environment%20%3D%20%7B%0Aproduction%3A%20true%0A%7D%3B” message=”src/environments/environment.prod.ts” highlight=”” provider=”manual”/]

  1. Now we can use the environment in any file by importing the interface and environment object:

[pastacode lang=”javascript” manual=”import%20%7B%20Environment%20%7D%20from%20′..%2Fenvironments%2Fenvironment.model.ts’%0Aimport%20%7B%20environment%20%7D%20from%20′..%2Fenvironments%2Fenvironment’%0A%0A…%0A%0A%2F%2F%20Simply%20grab%20the%20’production’%20property%0Aif%20(!environment.production)%20%7B%0Aconsole.log(‘This%20is%20a%20development%20build’)%0A%7D” message=”myapp.component.ts” highlight=”” provider=”manual”/]

By importing the interface, the properties of the environment object will be highlighted for us in certain IDEs and text editors. We’ll also be able to see if we’re trying to access properties that don’t exist.

Loading the Unique Source

Now that our project is configured to use environments, let’s manipulate the bootstrap process to load our Segment source.

In the previous article, I advised you to include the Segment snippet and load the service in your `index.html` file. I need to be honest: I mislead you. By keeping this code in your index, it’ll be hard-coded to a single source. We need to pull the analytics.load() and .page() methods out of the hardcoded template file, and into a class that only runs after Angular has been bootstrapped.

I prefer to do this in main.ts:

[pastacode lang=”javascript” manual=”%2F%2F%20Create%20a%20new%20window%20interface%20so%20analytics%20can%20be%20set%0Ainterface%20MyWindow%20extends%20Window%20%7B%0A%C2%A0analytics%3A%20any%3B%0A%7D%0A%0A…%0A%0A%2F%2F%20Bootstrap%20analytics%0Aconst%20mywindow%20%3D%20window%0A%0A%2F%2F%20If%20the%20Segment%20library%20has%20been%20successfully%20included%2C%20start%20tracking%20things%0Aif%20(mywindow.analytics)%20%7B%0A%C2%A0mywindow.analytics.load(environment.SegmentSourceKey)%0A%0A%C2%A0%2F%2F%20Now%20we%20can%20trigger%20events%2C%20such%20as%3A%20mywindow.analytics.page()%0A%7D” message=”” highlight=”” provider=”manual”/]

The Segment script adds an “analytics” method to the global `window` object that exposes its functionality. Similar to what we did for the AngularCLI environment config, we have to tell typescript about this. Unfortunately, Segment hasn’t provided the JS community with a TypeScript definition of their API, so here we’re using the dreaded `any`.

Also notice how we’re passing our Segment source key to the `load()` method. Now that it’s configured, let’s actually add our key by updating the environment interface and analytics environment:

[pastacode lang=”javascript” manual=”export%20interface%20Environment%20%7B%0Aproduction%3A%20boolean%3B%0ASegmentSourceKey%3F%3A%20string%3B%0A%7D” message=”src/environments/environment.model.ts” highlight=”” provider=”manual”/]

[pastacode lang=”javascript” manual=”import%20%7B%20Environment%20%7D%20from%20′.%2Fenvironment.model’%0A%0Aexport%20const%20environment%3A%20Environment%20%3D%20%7B%0Aproduction%3A%20false%3B%0ASegmentSourceKey%3A%20’…your%20analytics%20key%20goes%20here…’%3B%0A%7D” message=”src/environments/environment.analytics.ts” highlight=”” provider=”manual”/]

Now, when you run the project with the analytics environment, you will see that the Segment library is requested after the app loads. You can use your true Segment source key in the production environment.  If you don’t want to track analytics (such as in the dev environment), just leave out the property. A non-fatal 404 will be triggered when Segment tries to load an invalid source key and other segment events won’t be triggered.

– AJ Zane, Front End Engineer at Veyo

Part 3 in our series can be found here: Connecting Segment to Google Analytics