Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
analytics-client
Advanced tools
Convenient builders to compose analytics tools
Client part of analytics services used at balena. The analytics client is a component that integrates into the analytics-backend. Together they're responsible for processing the analytics tracking events before forwarding them to the relevant parties, referred to here as the final destinations. Currently the only final destination is Amplitude. We have plans to support more final destinations going forward, like Sentry.
npm install --save analytics-client
The first thing to do is create and initialize an analytics client
.
Since most of balena products are maintained on different components/repos (ie Hub, Marketing Site, Cloud, etc) we need to make sure that when someone navigates between components we can keep identifying it as a same id.
So to achieve that we will need to:
import { AnalyticsUrlParams, createClient} from 'analytics-client';
const urlParamsHandler = new AnalyticsUrlParams();
// This will handle any passed device id (d_id) param on the URL if it exists, save it on a cookie and return a "clean" query string without the d_id param
const newQuery = urlParamsHandler.consumeUrlParameters(window.location.search) ?? null;
// Then if there was any passed device id we can obtain them like this.
// passedDeviceId is either the first d_id param passed on the URL or null
const passedDeviceId = urlParamsHandler.getPassedDeviceId()
// Now that we checked for any passed device_id we can proceed with creating and initializing the client
const client = createClient({
endpoint: 'data.balena-cloud.com', // use 'data.balena-staging.com' for testing
projectName: 'balena-project', // unique identifier that analytics-backend expects
componentName: 'etcher-featured-project', // short unique name of component
componentVersion: require('./package.json').version, // (optional) automated version reporting
deviceId: passedDeviceId,
})
// A newly created client is passed to the `AnalyticsUrlParams` to make it fully functional.
urlParamsHandler.setClient(client);
Tracking a page view and a navigation click. The following reports an event named [EFP] Page View
and another event with [EFP] Navigation Click
with default properties.
import {createWebTracker } from 'analytics-client';
const webTracker = createWebTracker(client, 'EFP'); // 2nd parameter defines the prefix of event names
webTracker.trackPageView();
webTracker.trackNavigationClick('https://hub.balena.io'); // User clicks on a button to navigate to the Hub
Here is an example how a product like CLI would identify a user and report a login event ([CLI] Login
) with certain event properties related to the login action.
import { createClient } from 'analytics-client';
const client = createClient({
endpoint: 'data.balena-cloud.com', // use 'data.balena-staging.com' for testing
projectName: 'balena-project', // unique identifier that analytics-backend expects
componentName: 'balena-cli', // short unique name of component
componentVersion: require('./package.json').version, // (optional) automated version reporting
});
// user authenticates as part of the product flow
client.setUserId('balenaCloudUsername');
client.track('Login', {
balenaUrl: 'balena-cloud.com',
loginType: 'web-auth',
node: 'v10.21.0',
})
URL query parameters tool.
import { AnalyticsUrlParams } from 'analytics-client';
const urlParamsHandler = new AnalyticsUrlParams(mixpanel);
urlParamsHandler.consumeUrlParameters(window.location.search);
const signupUrl = '/signup?' + urlParamsHandler.getDeviceIdsQueryString();
UI experiments definition.
import { createClient, LocalExperiment } from 'analytics-client';
const client = createClient({projectName: 'my-project'});
type Variation = 'modal' | 'sidebar-left' | 'sidebar-right';
const experiment = new LocalExperiment<Variation>('WelcomeUI', client)
.define('modal', 50)
.define('sidebar-left', 25)
.define('sidebar-right', 25);
switch (experiment.engage(client.deviceId())) {
case 'modal':
showModal();
break;
// ...
}
Load the script from unpkg CDN (replacing {version}
with an actual version you need to use):
<script src="https://unpkg.com/analytics-client@{version}/dist/bundle.js"></script>
Then use the analyticsClient
variable:
const urlParamsHandler = new analyticsClient.AnalyticsUrlParams();
We use environment configuration on the analytics-backend to mask the actual API tokens of the final destination services of these events.
We expose easy to remember names to map the destination specific tokens to projectName
variable used as part of client initialization. analytics-backend uses the value of projectName
to reason where to pipe the event flow.
The masking helps with preventing abuse and the mapping makes the configuration more flexible to support multiple final destinations.
Reach out to the data team when in doubt which project to use or if you need to define a new project.
In the final destinations, we separate staging and production environments. We use the same projectName
value but different tokens to differentiate the production and staging environments. So you only need to update endpoint
to pick the right destination.
Use the staging environment for testing purposes by setting endpoint
in the createClient
initialization to data.balena-staging.com
. Once you are happy with your tests and ready to go live, update the endpoint
to data.balena-cloud.com
for production environment.
Additionally, identify your component using the parameter componentName
. It's best to keep the value short yet descriptive.
Please ask Operation folks for #access
to the relevant project in your final destination so you can validate that the tracked events show as expected.
Finally, there is the optional configuration parameter componentVersion
to track the version of a component sending each event. This is useful to track changes across new component versions so we strongly recommend tracking it.
WebTracker
exposes an events tracking interface suitable for web apps. It provides a simple Page View
event tracking with page loading metrics via trackPageView
.
When initializing createWebTracker
, set prefix
as a short string that describes your project. All events tracked by WebTracker
will have this prefix
in their name.
We use this prefixing method to identify and group events in the final destination for organization purposes and helping the analysts traverse the events with ease.
This is especially useful when there are multiple components sending events to the same project in the final destination. To give an example, our marketing website, docs pages and blog all send Page View
event but these are prefixed respectively Marketing
, Docs
and Blog
. So the final event name is [Marketing] Page View
, [Docs] Page View
, etc. Furthermore, this method makes it easier to identify all the Marketing
events.
By default the client tracks deviceId
to identify the current device of the end user. deviceId
is a UUID generated automatically by the client. Use setUserId
method to identify authenticated user. At least one of these identifiers is required to successfully track an event.
In most cases the device refers to the browser of the user (or Electron application for the case of Etcher). By persisting the deviceId
in the local storage, we are able to identify the events coming from the same user in order to create a timeline of component usage.
It is possible to generate a new device identifier and also override an existing device identifier. Additionally, when we record multiple device identifiers along with the same user identifier, we are able to link multiple event timelines coming from various devices belonging to the same user.
For instance, a balenaCloud user might login to the dashboard from multiple browsers and also use balenaCLI. We would like to create a coherent timeline that captures all their activity and display it under the same user in order to make a sound analysis of their balena platform usage. As long as all the components setUserId
as soon as the authentication happens, we are able to link all the events with separate deviceId
values that came even before the authentication on the backend side.
AnalyticsUrlParams
helps with linking anonymous deviceId
values that each component sends individually.
For instance we use this method to link Etcher users clicking on EFP link to land on our blog website and eventually signup to balenaCloud.
When the user clicks on the blog link in EFP, we append the deviceId
generated by EFP component to the URL.
Then the blog parses the URL to match EFP deviceId
with blog deviceId
(essentially the deviceId
associated with the browser that opened the blog website).
In a similar fashion, the signup links on the blog website also includes EFP deviceId
as well as blog deviceId
.
When the user lands on balenaCloud dashboard and authenticates, we link all the user activity and list it under the same timeline.
We need to make these jumps as there are 3 components tracking events and there are multiple domains involved.
The benefit is we are able to look into a user's EFP and blog activity before signing up to balenaCloud.
Reach out to the data team in r/analytics
flow for guidance and troubleshooting.
FAQs
Convenient builders to compose analytics tools
The npm package analytics-client receives a total of 2,431 weekly downloads. As such, analytics-client popularity was classified as popular.
We found that analytics-client demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.