Skip to content
This repository has been archived by the owner on Apr 28, 2022. It is now read-only.

analytics.js traits behave differently to Analytics for Android #656

Open
richardscarrott opened this issue Jan 29, 2021 · 2 comments
Open

Comments

@richardscarrott
Copy link

I'm designing our segment.io web integration and in the process I've found that analytics.js behaves differently to Analytics for Android with regards to traits.

The Android Identify documentation says:

Additionally, traits are sent in the context.traits field with every message.

For example:

window.analytics.indentify({
  first_name: 'Barry',
  last_name: 'From Eastenders'
});

// Sends
{
  // ...
  "type": "identify",
  "context": {
     // ...
  },
  "traits": {
    "first_name": "Barry",
    "last_name": "From Eastenders"
  }
}

Then a subsequent call to track or page:

window.analytics.track('Button Clicked', { button_name: 'Support' });

// Sends
{
  // ...
  "type": "track",
  "context": {
    // ...
    // Analytics for Android includes the traits from our previous identify call here, but analytics.js does not
    // "traits": {
    //    "first_name": "Barry",
    //    "last_name": "From Eastenders"
    // }
   },
  "properties": {
    "button_name": "Support"
  }
}

I'm not sure what iOS Analytics does or if the SDKs differ by design but I think it's a feature we'd like.

I have implemented it via a middleware, but before I went ahead with this it would be good to get some feed back re: why it's not done by default / whether it's a good or bad practice?

window.analytics.addSourceMiddleware(({ payload, next }) => {
  const traits = window.analytics.user().traits();
  payload.obj.context.traits = {
    ...traits,
    ...payload.obj.context.traits
  };
  next(payload);
});
@pbassut
Copy link

pbassut commented Mar 27, 2021

I'm facing the same issue. Analytics iOS does do that. Analytics.JS is the only one falling out of the bucket here

@richardscarrott
Copy link
Author

richardscarrott commented Mar 31, 2021

@pbassut we're using the following middleware in production which seems to be working ok.

export const contextTraitsMiddleware = () =>
  createMiddleware(({ payload, next }) => {
    const traits = window.analytics.user().traits();
    switch (payload.action()) {
      case 'page':
      case 'track':
        payload.obj.context.traits = {
          ...traits,
          ...payload.obj.context.traits
        };
        break;
    }
    next(payload);
  });

// ...
  
window.analytics.addSourceMiddleware(contextTraitsMiddleware());
const createMiddleware = (
  fn: (input: SegmentAnalytics.SourceMiddlewareInput) => void
) => (input: Parameters<typeof fn>[0]) => {
  // Wait until analytics is ready so we can access the full API (e.g. window.analytics.user().traits())
  window.analytics.ready(() => {
    try {
      fn(input);
    } catch (ex) {
      // Report errors to our servers (and the console) as segment appears to swallow them (perhaps they report it to their own servers?)
      reportError(ex);
      throw ex;
    }
  });
};

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants