Giter VIP home page Giter VIP logo

analytics.js-core's Introduction

โš ๏ธ This library is in End of Support status as of 08/31/2022 and is replaced with Analytics.js 2.0.

https://github.com/segmentio/analytics-next

If you have an existing JavaScript source with Segment, you can enable Analytics.js 2.0 in the settings of the source.

analytics.js-core

CircleCI Codecov

This is the core of Analytics.js, the open-source library that powers data collection at Segment.

To build this into a full, usable library, see the Analytics.js repository.

Using Types (v.4.0.0-beta.0 and later)

We recently introduced Typescript support and types to Analytics.js Core. While the exposed types still need some work (pull requests are welcome!), they're ready to be used.

Importing as an npm module

If you use analytics.js-core as an npm module, you can use its types out of the box: Example of Types usage in Analytics JS

Using types with the AJS Snippet

If you create a source at https://app.segment.com, Segement automatically generates a JS snippet that you can add to your website. (for more information visit our documentation).

To use types with the snippet, add analytics as part of the global module. Something like this:

import { SegmentAnalytics } from '@segment/analytics.js-core';

declare global {
  interface Window {
    analytics: SegmentAnalytics.AnalyticsJS;
  }
}

Using as a standalone npm package

We recommend using the CDN version of analytics.js as it offers all the project and workspace specific settings, enabled integrations, and middleware. But if you prefer to use analytics.js-core as a standalone npm package using your own tooling & workflow, you can do the following:

1- Install the dependencies

yarn add @segment/analytics.js-core
yarn add @segment/analytics.js-integration-segmentio
// you may need this depending on the bundler
yarn add uuid@^3.4 

2- Import the dependencies

import Analytics from "@segment/analytics.js-core/build/analytics";
import SegmentIntegration from "@segment/analytics.js-integration-segmentio";

3- Initialize Segment and add Segment's own integration

// instantiate the library
const analytics = new Analytics();

// add Segment's own integration ( or any other device mode integration ) 
analytics.use(SegmentIntegration);

// define the integration settings object. 
// Since we are using only Segment integration in this example, we only have 
// "Segment.io" in the integrationSettings object
const integrationSettings = {
  "Segment.io": {
    apiKey: "<YOUR SEGMENT WRITE KEY>",
    retryQueue: true,
    addBundledMetadata: true
  }
};


// Initialize the library
analytics.initialize(integrationSettings);

// Happy tracking! 
analytics.track('๐Ÿš€');

License

Released under the MIT license.

analytics.js-core's People

Contributors

amillet89 avatar araddon avatar aultimus avatar azcoov avatar bryanmikaelian avatar calvinfo avatar ccnixon avatar coryvirok avatar danieljackins avatar devangpaliwal avatar dkador avatar dominicbarnes avatar f2prateek avatar fathyb avatar ianstormtaylor avatar jessbrandi avatar jlee9595 avatar juliofarah avatar lancejpollard avatar mchail avatar midudev avatar ndhoule avatar nscott avatar peripheral1994 avatar philfreo avatar robv avatar rowno avatar simontabor avatar sperand-io avatar yields 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  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

analytics.js-core's Issues

Types are an empty object

Issue and steps to reproduce.
npm i @segment/analytics.js-core

Versions.
Latest

Screenshots.
image

Expected result.
To see there types

Actual result.
export {};

Compile warning

Using 4.1.1

Compiled with warnings.

./node_modules/@segment/analytics.js-core/build/index.js
Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

Use beacons in trackLinks for supporting browsers

Currently trackLinks adds a 300ms timeout to links to allow enough time for the analytics to fire, but beacons solves this issue without the performance overhead + all modern browsers now support it (https://caniuse.com/#search=beacon)

I'd love to see beacon support added (with the 300ms timeout left for unsupporting browsers).

Additionally, what do you guys think about adding a new trackLink function that can be added directly as an onclick to a link (rather than requiring a selector)? I feel like this API would be nicer for devs building out component-architected UI's.

node-uuid V2 is deprecated

node-uuid v2 is deprecated. As it is used only to generate anonymousId v4, it should be updated to uuid v3.

Thanks

amplitude does not load

we load scripts with crossOrigin="anonymous" as described in requirejs/requirejs#687

    var requirejs_createNode = requirejs.createNode;
    requirejs.createNode = function createNodeAddCors( config, moduleName, url ) {
        var node = requirejs_createNode(config, moduleName, url);
        node.crossOrigin = "anonymous";
        return node;

But the https://d24n15hnbwhuhn.cloudfront.net/libs/amplitude-2.4.1-min.gz.js does not load

Script from origin 'https://d24n15hnbwhuhn.cloudfront.net' has been blocked from loading by Cross-Origin Resource Sharing policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://our-server.com' is therefore not allowed access.

Please avoid using global window.require or ensure the integration works with crossOrigin="anonymous"
crossposting from segmentio/analytics.js#487

Udgrade [email protected] to v7 or v8 since it's deprecated

Hello :D

I am getting this warning when running yarn install with yarn 2, using @segment/analytics.js-core@^4.1.11.

uuid@npm:3.4.0 is deprecated: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.

image

I realized this package is using [email protected] and I think is a good idea to upgrade it to v7 or v8.

My project is private so I can't add the link here.
My OS is Ubuntu 20.04.

Instructions for using node module do not work

The instructions say

// instantiate the library
const analytics = new Analytics();

When I try to do this it says:
"/node_modules/@segment/analytics.js-core/build/analytics")' has no construct signatures."

TypeError: 'undefined' is not a function (evaluating 'analytics.load('key')

Your Quickstart Guide states to perform the following steps to load analytics:

<script type="text/javascript">
  !function(){var analytics=window.analytics=window.analytics||...
  analytics.load("YOUR_WRITE_KEY");
  analytics.page()
  }}();
</script>

However, there is no documentation about how to use the analytics.js as, i.e. a bundled node package.

Something like the following:

var analytics = require('analytics.js');

analytics.load('abc');

Results in an error:

TypeError: 'undefined' is not a function (evaluating 'analytics.load('key')

It's clear that this the JS contained in this repository is not the same as the minified JS in the Getting Started example.

How do you explain that? Why doesn't the .load method work?

Please help!

Thanks!
-Lee

Using link(rel="canonical") is not SPA friendly

This part of the code affects many SPAs defaults:

path: canonicalPath(),

Asuming HTML structure is correct is an old fail from many browsers IMHO. jQuery understood it perfectly on it's Sizzle engine that ids are still going to be duplicated in the same DOM context.

Anyway, the thing is that if in the first load of the page, your server framework delivers a canonical path in a link(rel="canonical"), and your SPA framework does not handle it on each push state change, the reported path and url properties is always the one from the first load, and not the actual page as it should.

I'm not sure if this was an intended behavior neither it's reasons. I just think there should be a way to turn this off at least.

Thanks!

Warn if continue to use shim after real analytics loaded?

#59 is unresolved.

I'm creating a new issue because I'm currently trying to resolve this problem and workarounds described in #59 are not working for me.

Description of the issue copied from #59:

I had some code that looked like this:

const analytics = window.analytics;

function page() {
  analytics.page(...)
}

It worked completely fine except in the rare case that the code ran before analytics.js was loaded.

In such cases the analytics.page() call still works and is queued by the snippet, to be flushed later by the true Analytics object (once it loads), I suppose. But the subtle bug in the above is that the reference const analytics above will in such cases always point to the shim! So future calls to page() will just not do anything (they will make calls on the now discarded shim).

Can I suggest to help future people who run into this that when you flush the messages from the shim, you also set the existing "factory" functions to throw and point users to some documentation explaining where they might be going wrong?

Is this Library Tree-Shakable?

From the docs it appears that this is a JS dependency library for

https://cdn.segment.com/analytics.js/v1/analytics.min.js

I think we may only be using the track, reset and identify syntaxes and not the others.
And from the readme it appears that we can tree-shake this so I just want to confirm this in advance.

Track callback not based on request.

Correct me if I'm wrong, but it is my understanding that the callback passed into analytics.track is based on an arbitrary amount timeout rather than the status of the xhr request. Is there a reason for this? could it be changed? Currently there is no way to verify a tracking request has been made before executing my callback. We are using the customer.io integration and would like to have more confidence in our tracking events.

Allow analytics.js to run without cookies

Background

The EU ePrivacy regulation (ePR) gives users a lot more rights when it comes to the data that websites can store on their machines, in cookies, localStorage and the like. One focus is to let users opt-out of third-party companies being able to track them across the web, when that company has scripts embedded on multiple sites - like Segment. So far, hopefully nothing controversial.

analytics.js uses cookies or localStorage to persist user identifiers - anonymous, group and user IDs - between page loads. A site can identify a user on one page and Segment will know it's the same person the next time they load a page. Or, Segment will know that an anonymous user is the same person who loaded a page earlier.

Everything above is objective, but there are a couple of subjective points that apply to our situation, and any other people who have come to the same conclusions as us:

  • Our reading of the ePR leads us to believe that users should even be able to opt-out of first-party cookies that aren't strictly necessary for their use case, and this even includes site metrics. I realise this may not be a universal interpretation but it's ours - this Github issue probably isn't the right place to have a legal discussion.

  • Segment's analytics.js first party cookies (ajs_*) by themselves don't technically enable cross-site tracking, but can be blocked by users as a consequence of the point above.

Issue

Because of the way analytics.js-core automatically sets cookies based on whether the browser has cookies enabled or not, we can't load analytics.js at all if a user has told us they don't want our "Functional" cookies. This leaves us missing out on Segment functionality, which is sad.

However, my understanding (to be confirmed) is that cookies aren't strictly necessary for Segment to do its thing. Given some additional restrictions, it should be possible for the existing analytics library to work without setting cookies:

  1. If we're happy that we don't need to track events from anonymous users
  2. If we're happy to call identify on each individual page load before any events are tracked.

This is all based on the fact that Entity.js has a fallback for a memory store which Segment can use if cookies and localStorage are unavailable.

The only thing that is missing to make this happen is a way to override the browser-based checks and force Segment to use the memory store.

I guess I have two questions:

  1. Is my understanding of this correct - that the two restrictions above mean Segment could โ€“ in theory โ€“ work without cookies?

  2. If it's possible, would a community-provided PR be enough to get this considered for inclusion in Segment?

At the moment, our only option to track client-side events is to write our own probably-clumsy javascript wrapper around your HTTP API, and miss out on most of the simplicity of analytics.js.

@segment/cookie not found in npm registery

Is @segment/cookie a published package?

It is listed as a new dependency in the last version!

I started getting:

error Couldn't find package "@segment/cookie@^1.1.5" required by "@segment/analytics.js-core@^3.9.0" on the "npm"
 registry.         

analytics.identify and analytics.page options arguments interfere with eachother

I'm testing this with Intercom, and getting really weird behavior: for example, this options array:

options = { integrations: { 'All': false } }
analytics.identify( 123, { ... }, options )
analytics.page()

causes intercom JS to still run on the page, and a javascript error appears (invalid user_hash for intercom, because I am not sending intercom the sign-in data it wants. But it should not be running at all).

If I do this, however, no intercom JS runs on the page, and no error appears:

options = { integrations: { 'All': false } }
analytics.identify( 123, { ... }, options )
analytics.page(null, null, null, options)

Notice that I am sending "options" to both identify and page

If I only send the "options" object to page but not to identify, I'm back to the same javascript error message. This seems goofy and isn't documented; can you add a note about this to the docs here https://segment.com/docs/sources/website/analytics.js/#selecting-integrations ?

update facade to 2.x

Not sure if there's a reason why, but analytics.js tracks the 1.x branch of facade. Makes maintenance kinda hard and also means we've missed out on a bunch of improvements (e.g. cloning/traverse spring to mind)

cc @yields @gjohnson, any missing context here I should know about?

Setting custom `campaign` properties

Hello. I cannot seem to get custom campaign properties sent in context for a page call.

Here is the code on the page:

!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on"];analytics.factory=function(t){return function(){var e=Array.prototype.slice.call(arguments);e.unshift(t);analytics.push(e);return analytics}};for(var t=0;t<analytics.methods.length;t++){var e=analytics.methods[t];analytics[e]=analytics.factory(e)}analytics.load=function(t){var e=document.createElement("script");e.type="text/javascript";e.async=!0;e.src=("https:"===document.location.protocol?"https://":"http://")+"cdn.segment.com/analytics.js/v1/"+t+"/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(e,n)};analytics.SNIPPET_VERSION="4.0.0";
	analytics.load("<key>");

	function getQueryVariable(variable) {
    	var query = window.location.search.substring(1);
    	var vars = query.split("&");
    	for (var i=0;i<vars.length;i++) {
        	var pair = vars[i].split("=");
        	if(pair[0] == variable){return pair[1];}
    	}
    	return(void 0);
	}

	var campaign = {
        name: getQueryVariable("ctx_campaign"),
        source: getQueryVariable("ctx_source"),
        medium: getQueryVariable("ctx_medium"),
        term: getQueryVariable("ctx_term"),
        content: getQueryVariable("ctx_content")
    }

	window.console && window.console.log && window.console.log('campaign', campaign)

	analytics.page({}, {
      	context: {campaign: campaign},
     	campaign: campaign
	});
}}();

The campaign object prints correctly to the console. However, the API call does not include campaign:

{
  "context": {
    "campaign": {
      
    },
    "page": {
      "path": "\/offer",
      "referrer": "",
      "search": "?ctx_source=spaintrain&ctx_term=spain,train&ctx_campaign=spainzy",
      "title": "[Pricing - Step 1] Pricing.Full.Length.1.20",
      "url": "http:\/\/pricing-analysis.myhomezen.com\/offer?ctx_source=spaintrain&ctx_term=spain,train&ctx_campaign=spainzy"
    },
    "userAgent": "Mozilla\/5.0 (X11; Linux x86_64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/56.0.2924.87 Safari\/537.36",
    "library": {
      "name": "analytics.js",
      "version": "3.0.0"
    }
  },
  "integrations": {
    
  },
  "properties": {
    "path": "\/offer",
    "referrer": "",
    "search": "?ctx_source=spaintrain&ctx_term=spain,train&ctx_campaign=spainzy",
    "title": "[Pricing - Step 1] Pricing.Full.Length.1.20",
    "url": "http:\/\/pricing-analysis.myhomezen.com\/offer?ctx_source=spaintrain&ctx_term=spain,train&ctx_campaign=spainzy"
  },
  "category": null,
  "name": null,
  "anonymousId": "be16ec17-7f10-4f70-9072-df5491ce78ec",
  "timestamp": "2017-02-24T23:25:04.878Z",
  "type": "page",
  "writeKey": "<key>",
  "userId": "<id>",
  "sentAt": "2017-02-24T23:25:04.881Z",
  "_metadata": {
    "bundled": [
      "AdRoll",
      "Amplitude",
      "Facebook Pixel",
      "Google Analytics",
      "Google Tag Manager",
      "Lucky Orange",
      "Mixpanel",
      "Segment.io"
    ],
    "unbundled": [
      
    ]
  },
  "messageId": "ajs-55423f6e71370b8998553bd7d25c2009"
}

It is possible to see this live at https://pricing-analysis.myhomezen.com/offer?ctx_source=spaintrain&ctx_term=spain,train&ctx_campaign=spainzy

It seems to be supported, because I updated the page event test like so and it still passes:

    it('should accept top level option .context', function() {
      var app = { name: 'segment' };
      var campaign = { name: 'segment' };
      analytics.page({ prop: true }, { context: { app: app, campaign: campaign } });
      var page = analytics._invoke.args[0][1];
      assert.deepEqual(app, page.obj.context.app);
      assert.deepEqual(campaign, page.obj.context.campaign);
    });

Is this intended to be supported? If so, pointers on where to look next to find the issue?

'global' id in HTML tag causes analytics.js to fail badly

If you, as I do, have a page with, say, a <div id="global">...</div> then analytics.js will load and run via the snippet, but will not overwrite the window.analytics variable and playback the stubbed call queue. A call to page() will be made with the defaults, but that's the only sign that anything at all happened.

And, yes, this absolutely gave me fits while trying to debug...

Cannot use with webpack

Hi,

import * as analytics from '@segment/analytics.js-core';

Fails with webpack. Warning

WARNING in /node_modules/@segment/analytics.js-core/lib/index.js
15:20-27 Critical dependency: require function is used in a way in which dependencies cannot be statically extracted

Because of this line transpiled into

analytics.require = !(function webpackMissingModule() { var e = new Error("Cannot find module \".\""); e.code = 'MODULE_NOT_FOUND'; throw e; }());

Everything works fine without it. If this is deprecated could you please remove it ? Do you need a PR for it ?

Will have a look at ContextReplacementPlugin because seems related to webpack/webpack#2670 and webpack/webpack#2675

User overrides of 'properties' on '.page' call are not honored

Hi there!

I think I found a bug in how the .page call does overrides:

Environment

node: 12.19.1
@segment/analytics.js-core: 4.1.5
@segment/analytics.js-integration-segmentio: 4.2.5

Setup

Setup Similar to https://github.com/segmentio/analytics.js-core

Observed results

When making the following call (using Vue):

    // Make a page call for each navigation event
    analytics.page(undefined, to.name || '', {
      path: to.fullPath,
      referrer: from.fullPath,
    });

the analytics tracked on Segment actually returns the default obtained by the document

Expected Results

Page and referrer should get overridden, as specified on the doc

Thoughts

I see on this commit a FIXME that might be related to this issue, though I am not 100% sure.

If anything, the old code seem to propagate user overrides correctly into the context.page object, while the new code doesn't because properties gets overridden the other way around by the statement:

properties = {
    ...properties,
    ...defs
  }

before it gets any chance to make it to context.page.

Thank you!

pageDefaults.searchPath drops last character in query string

The current implementation of pageDefaults.searchPath removes the last character in the query string. https://github.com/segmentio/analytics.js-core/blob/master/lib/pageDefaults.js#L70. The second parameter to url.slice is -1, which specifies to drop the last character.

Docs for String.prototype.slice: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice

Example

var url = 'https://github.com/segmentio/analytics.js-core?param=test';
var u = url.indexOf('?');
var result = u === -1 ? '' : url.slice(u, -1); // returns ?param=tes

Expected

var url = 'https://github.com/segmentio/analytics.js-core?param=test';
var u = url.indexOf('?');
var result = u === -1 ? '' : url.slice(u); // returns ?param=test

I can make the change and submit a pull request if you'd like.

'Unexpected token export' in test

Hi team,

I'm using a fork of analytics.js-core and the recent changes to the bind-all repo (which I think was transferred) made it impossible to build our version. I updated to yesterday changes (which appear to fix that problem) but the tests are failing (make test) and make test browser). Seems they're also failing in CircleCI on your side.

Seems like there's a package using an 'export' construction that the browser doesn't like.

Wondering if that's something you were aware of and how to fix it?

Cheers

Protocol and domain are missed with canonical url

If canonical URL is present it's value is used as context.page.url value.
Unlike window.location.href or href attribute of <a> tag, canonical tag doesn't convert absolute or relative path to fully qualified url.
For example for <link rel="canonical" href="/absolute/path" /> returned value will be "/absolute/path".
In such case, it's not possible to guess protocol and domain from an event data.

Instructions are wrong

Using 4.1.1.

Again, instructions say

// Initialize the library
analytics.initialize(integrationSettings);

This function does not exist?

Did anyone actually try following the instructions before releasing this?

Default page event canonical path is always '/'

When triggering analytics.page() as per the installation snippet, debugger reports '/' for all pages.

is canonicalPath() supposed to return '/' always? Or is there some tags we should be aware of that is being used and should not be overridden.

On analytics.js the default analytics.page() request defaults to:

analytics.page({
  path: '/',
  referrer: 'http://localhost:3000/',
  search: '',
  title: 'Grain - Log in | Delightful food delivery in Singapore',
  url: 'http://localhost:3000/'
});

On ruby library, we specify the values directly and the request is as such for the same page load:

Analytics.page(
  name: '/login',
  properties: {
    user_id: 'G-7243',
    title: 'Grain - Log in | Delightful food delivery in Singapore',
    url: 'http://localhost:3000/login',
    path: '/login',
    referrer: 'http://localhost:3000/',
    http_method: 'GET'
  }
)

Avoid exposing the full package.json in the build

Hi,

While building my own version of analytics.js, I found that the full content of package.json from this package is exposed into the resulting build.
The faulty line is

analytics.VERSION = require('../package.json').version;

I would suggest to use package-json-versionify, either by adding the transform in the package.json or by updating analytics.js and using a global transform.

Note: the content is also exposed in the segment's build.

Default Context

Hey everyone!

What do you all think about adding the ability to pass a default context? The use case is needing to pass the same context to all events, implicitly, so we don't copy-pasta it all over.

It seems we could almost do this with .initialize(), but that is already being called by the hosted version of analytics.js via the cdn. So maybe adding something like:

analytics.options = {
  context: {
    foo: bar
  }
}
analytics.load('xxx')
analytics.page()

I think this would be possible by just merging here instead of assigning?

this.options = options;

I'm glad to make the change(s) if you all are down for them :-)

analytics.min.js contains junk that doesn't belong there

We were investigating a performance problem on our page and noticed that the analytics.min.js file that's included on our pages has a bunch of metadata that doesn't belong in there.

It's potentially useful that the Github commit ID is included, for debugging purposes, but I really don't want to have all of your maintainers' email addresses loaded on my page. That's a potential GDPR concern.

gitHead":"a2ad22ca8df361ac7439510fe468c1fa9bf5f3ab","homepage":"https://github.com/segmentio/analytics.js-core#readme","keywords":["analytics","analytics.js","segment","segment.io"],"license":"SEE LICENSE IN LICENSE","lint-staged":{"linters":{"*.{js,json,md}":["prettier-eslint --write","git add"]}},"main":"lib/index.js","maintainers":[{"name":"achille-roussel","email":"[email protected]"},{"name":"alan-segment","email":"[email protected]"},{"name":"albert.segment","email":"[email protected]"},{"name":"amillet89","email":"[email protected]"},{"name":"andreiko_ru","email":"[email protected]"},{"name":"anoonan","email":"[email protected]"},{"name":"atrivedi1","email":"[email protected]"},{"name":"bgamwell","email":"[email protected]"},{"name":"boggsboggs","email":"[email protected]"},{"name":"calvinfo","email":"[email protected]"},{"name":"carlosmecha","email":"[email protected]"},{"name":"ccnixon","email":"[email protected]"},{"name":"chenpengcheng","email":"[email protected]"},{"name":"chrisbuttery","email":"[email protected]"},{"name":"colinking","email":"[email protected]"},{"name":"cyrusroshan","email":"[email protected]"},{"name":"dfuentes","email":"[email protected]"},{"name":"dominicbarnes","email":"[email protected]"},{"name":"dscrobonia","email":"[email protected]"},{"name":"eesegment","email":"[email protected]"},{"name":"emilio-gomez-lavin","email":"[email protected]"},{"name":"emily.luckette","email":"[email protected]"},{"name":"erickimsegment","email":"[email protected]"},{"name":"estela-diaz","email":"[email protected]"},{"name":"f2prateek","email":"[email protected]"},{"name":"fathyb","email":"[email protected]"},{"name":"fforres","email":"[email protected]"},{"name":"flaque","email":"[email protected]"},{"name":"gnijor","email":"[email protected]"},{"name":"hanothan","email":"[email protected]"},{"name":"ivolo","email":"[email protected]"},{"name":"jamesmcguinness","email":"[email protected]"},{"name":"jeroenransijn","email":"[email protected]"},{"name":"jfabre-segment","email":"[email protected]"},{"name":"jfarah","email":"[email protected]"},{"name":"jfmaggie","email":"[email protected]"},{"name":"jlee9595","email":"[email protected]"},{"name":"joeybloggs","email":"[email protected]"},{"name":"josh_segment","email":"[email protected]"},{"name":"joshwget","email":"[email protected]"},{"name":"ladanazita","email":"[email protected]"},{"name":"lauramunozjimenez","email":"[email protected]"},{"name":"leifdreizler","email":"[email protected]"},{"name":"mag"},{"name":"maxence-charriere","email":"[email protected]"},{"name":"monicadamborenea","email":"[email protected]"},{"name":"msanterre","email":"[email protected]"},{"name":"mshwery","email":"[email protected]"},{"name":"n2parko","email":"[email protected]"},{"name":"nettofarah","email":"[email protected]"},{"name":"notfelineit","email":"[email protected]"},{"name":"nucleartide","email":"[email protected]"},{"name":"nzoschke","email":"[email protected]"},{"name":"peripheral","email":"[email protected]"},{"name":"rarchana2001asu","email":"[email protected]"},{"name":"rlc4","email":"[email protected]"},{"name":"rowno","email":"[email protected]"},{"name":"rpaul80","email":"[email protected]"},{"name":"sahilp","email":"[email protected]"},{"name":"segment-admin","email":"[email protected]"},{"name":"segment-anastassia","email":"[email protected]"},{"name":"segment-andy-yeo","email":"[email protected]"},{"name":"segment-cyammine","email":"[email protected]"},{"name":"segment-danielstjules","email":"[email protected]"},{"name":"segment-scott","email":"[email protected]"},{"name":"segment-ulysse","email":"[email protected]"},{"name":"segmentaimee","email":"[email protected]"},{"name":"segmentio","email":"[email protected]"},{"name":"segmentmfischer","email":"[email protected]"},{"name":"sperand-io","email":"[email protected]"},{"name":"srthurman","email":"[email protected]"},{"name":"systemizer","email":"[email protected]"},{"name":"tamarrow","email":"[email protected]"},{"name":"tejasmanohar","email":"[email protected]"},{"name":"tyson_segment","email":"[email protected]"},{"name":"vdemedes","email":"[email protected]"},{"name":"willallison","email":"[email protected]"},{"name":"williams-blake","email":"[email protected]"},{"name":"xagos","email":"[email protected]"},{"name":"yields","email":"[email protected]"}],

Vulnerable is-email dependency in 4.1.11

I have "@segment/analytics.js-core": "4.1.11", installed.

When running npm audit I get the following error:

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ High          โ”‚ Improper Input Validation in is-email                        โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Package       โ”‚ is-email                                                     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Patched in    โ”‚ >=1.0.1                                                      โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Dependency of โ”‚ @segment/analytics.js-core                                   โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ Path          โ”‚ @segment/analytics.js-core > segmentio-facade > is-email     โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ More info     โ”‚ https://github.com/advisories/GHSA-j377-2x76-558h            โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

I understand that there is a fix for is-email, but since segmentio-facade depends on the exact version 0.1.0 I'm not sure if it is compatible.

Can you update the dependencies for segmentio-facade and @segment/analytics.js-core that they don't use is-email 0.1.0?

Warn if continue to use shim after real analytics loaded?

I had some code that looked like this:

const analytics = window.analytics;

function page() {
  analytics.page(...)
}

It worked completely fine except in the rare case that the code ran before analytics.js was loaded.

In such cases the analytics.page() call still works and is queued by the snippet, to be flushed later by the true Analytics object (once it loads), I suppose. But the subtle bug in the above is that the reference const analytics above will in such cases always point to the shim! So future calls to page() will just not do anything (they will make calls on the now discarded shim).

Can I suggest to help future people who run into this that when you flush the messages from the shim, you also set the existing "factory" functions to throw and point users to some documentation explaining where they might be going wrong?

[Apologies if I am using the wrong terminology, I'm not what vocabulary you use for this stuff].

Allow 'options' param in 'trackLink' method

Since trackLink method is calling the track method under the hood, it should support the same parameters.

i.e. analytics.trackLink(element, event, [properties], [options]);

Thanks!

React Native support?

I'm currently stuck wrestling with react native mobile app and I'm currently trying to get some sort of analytics plugged into it. There are a few libs out there that help, but only partially:

image

Right now

import Analytics from 'analytics.js'
const analytics = Analytics({
  writeKey: process.env.SEGMENT_KEY,
  skipPageCall: true
})

Gives me a "cannot find module "771"" error. Any idea what's going on here?

No way to determine if anonymousID is set without setting it

We've recently moved to a server-side rendering setup, and as part of that we are also starting to run rendering experiments.

This requires our server to know the anonymous ID server-side, as we will use this as the input into the experiment switching logic. This is all well and good when the user has visited our site before, as on the server we can read the ajs_anoymous_id cookie.

However, when this is the users first visit to our site, OR when it is the first visit to a subdomain on our site, we don't know the anonymous ID server-side as there are no cookies yet, so we make one up, hoping to set it as a permanent ID client-side, but also accepting that once the client code runs, it may be overriden by analytics.js.

In this case we would like to:

  • Have the server decide an anonymous ID for the user and use this for SSR experiment rendering
  • Send it back with the initial page response
  • Before the analytics.js load call is made, check to see if analytics.js actually does have a known anonymous ID (from another domain, cookie, or localStorage) *
  • If it does not, then we want to call analytics.setAnonymousId(ourServerGeneratedAnonId)
  • If it does, then we will leave it as is, and accept that our SSR used an incorrect anonymous ID for rendering (hopefully rare)

I have all this wired up, except * - as calling analytics.load immediately sets the anonymous ID if it doesn't exist, so I can't tell when to override or not without manually looking at localStorage, cookies, and trying to re-create the logic inside analytics.js code.

Proposal

I would like to add a public API to analytics.js that can return the currently known anonymous ID without setting it to a new UUID if it doesn't exist, or a way to set the anonymous ID only if it doesn't already exist.

This would enable a few things, not only server side-experiments, but also server side tracks and pages that use the same anonymous ID as the client.

I'm happy to send a PR if there is agreement, or if there are any suggestions for workarounds, I'm all ears!

Analytics Node library on the client

Hello,

I am using node version of the library on the client to send data to Segment and I was wondering what's the correct way to set context.ip field to get the value of the client IP address inferred automatically by Segment?

Thanks

Broken, missing, and old dependenices

Hi team, I recently attempted to follow the directions for testing with the docs in @segment/analytics.js-integration-tester but I can't seem to get it running in Jest. See the screenshot attached.

-zsh+2021-03-06+at+2 10 28+PM

Steps to reproduce:

In particular, it looks like the Analytics core is utilizing old component organization dependencies. The organization itself is now asking people to move off of their code and utilize alternatives, including the dependency component-querystring.

It looks like there are several other component packages that need to be migrated as well:
https://github.com/segmentio/analytics.js-core/blob/master/package.json#L42-L46

Additionally, this dependency is not listed at all in the package.json but utilized in the build @ndhoule/defaults:
-zsh+2021-03-06+at+2 20 35+PM

Let me know if you need anything else!

Page overrides aren't being passed through on .track calls

I have a use case for wanting to change the referrer on all calls to segment, this is due to sensitive data being in there.

So this works great on the .page call, if I supply a properties object containing some of the reserved page keywords, namely url and referrer, they get overridden, however it falls over on any other calls, namely the .track call in my case.

Looking into the code, it seems .page is unique in that it overrides options.context if there are supplied properties that fit the overrides (

var overrides = pick(keys(defs), properties);
), .track does not do this, and I was wondering if there was a reason for this?

I'm happy to do a PR if this is desired functionality, just need a thumbs up from the team. ๐Ÿ˜„

(I'm also wondering if all calls should have a way to override context?)

Why to revert 4.1.0-4.1.7. Can I still use the code from my fork.

I'm keeping a fork to trim unnecessary code for my case to minimize the bundle size.

I just notice that for the last month or so, you've hard reverted 4.1.0-4.1.7. Were there security issues?

And I love those commits to replace local utils with lodash. How's the next official plan to continue?

No types for import SegmentIntegration from "@segment/analytics.js-integration-segmentio";

Trying to import as per the documentation doesn't work

import SegmentIntegration from '@segment/analytics.js-integration-segmentio

Could not find a declaration file for module '@segment/analytics.js-integration-segmentio'. react/node_modules/@segment/analytics.js-integration-segmentio/lib/index.js' implicitly has an 'any' type.
Try npm install @types/segment__analytics.js-integration-segmentio if it exists or add a new declaration (.d.ts) file containing declare module '@segment/analytics.js-integration-segmentio';ts(7016)

Uncaught TypeError: e.replace is not a function in Product added

I'm getting this error randomly (but seems to be related to Product Added event), the problem seems to be here

function a(e) { return e.replace(c, function(e, t, n) { return t + " " + n.toLowerCase().split("").join(" ") }) }

located at

347: [function(e, t, n) { ;function o(e) { return r.test(e) ? e.toLowerCase() : s.test(e) ? (i(e) || e).toLowerCase() : a(e).toLowerCase() } function i(e) { return e.replace(l, function(e, t) { return t ? " " + t : "" }) } function a(e) { return e.replace(c, function(e, t, n) { return t + " " + n.toLowerCase().split("").join(" ") }) } t.exports = o; var r = /\s/ , s = /[\W_]/ , l = /[\W_]+(.|$)/g , c = /(.)([A-Z]+)/g; }

I'm using latest version.
Any help?

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.