2

I'm using TrackJS in SPA, i have logic related to GDPR, so I can NOT send any data before consent given.

I found onError config option which help with this. But i still have external request to https://usage.trackjs.com/usage.gif. I can disable this by some tricks but it doesn't looks correct way.

So how to prevent usage call?

Example of implementation:

import { TrackJS } from 'trackjs';

let GLOBAL_VARIABLE_IS_CONSENT_GIVEN = false;

TrackJS.install({
  usageURL: '#', // disable usage call
  onError: function() {
    if (!GLOBAL_VARIABLE_IS_CONSENT_GIVEN) {
      return false;
    }

    // other logic

    return true;
  },
});

I also found issue with usage call in SPA. It will not show actual page view result. So it will be good to have support to call usage request manually, it will solve two issues above. Found that it's known limitation: https://docs.trackjs.com/data-management/pageviews/

Alexandr Vysotsky
  • 1,081
  • 13
  • 16

2 Answers2

2

Todd from TrackJS front end error monitoring here. I don’t believe you need to short-circuit the call to usage for GDPR, as it does not contain any user-specific data. It is simply a counter of how many times a given application has been loaded.

Usage only sends:

  • Account Token
  • Application I’d
  • Generated Identifier for uniqueness

None of these trace back to the user, so you should be able to go ahead and allow the usage call to happen, and use the method you described to block errors from being sent in onError.

Alternatively, I’d recommend you delay the call to TrackJS.install until after consent is gained. The downside to this approach is that errors that happen before consent are not captured. But I guess that’s what the user wanted?

Todd H. Gardner
  • 630
  • 4
  • 18
  • It's not our case to delay initialise, because we can lose significant part of errors for all customers, so we should initialise TrackJS before all or it will not really useful. I read you twitter post https://twitter.com/trackjs/status/981971836010418184 that you are GDPR complian, but our legal who responsible for GDPR, said "being GDPR compliant is not the same as being Essential". For me as developer best option will be extend your API to allow block your usage call. It this case we will be sure that no "Not Essential" calls are sent before consent given. Is it possible? – Alexandr Vysotsky Oct 09 '19 at 06:51
  • What if you add support to call usage request manually, it will be solve at least two issue: GDPR and navigation in SPA. – Alexandr Vysotsky Oct 10 '19 at 08:28
  • Updated question description – Alexandr Vysotsky Oct 10 '19 at 09:12
1

At the current moment I found only one way to solve it. I wrote helper class which apply monkey patch to prevent sending usage call and error tracking until it allowed. Monkey patch is usually practiced when you need to block loading external scripts, e.g. iubenda which we already use.

Helper class:

class TrackJSUtil {
  static URL_PATTERN = /usage\.trackjs\.com/;

  /**
   * Keep usage url
   *
   * @private
   * @type {null|string}
   */
  usageUrl = null;

  /**
   * Is requests allowed
   *
   * @private
   * @type {boolean}
   */
  isRequestsAllowed = false;

  /**
   * Apply monkey patch
   */
  install() {
    if (this.isRequestsAllowed) {
      return;
    }

    const setUsageUrl = (value) => {
      this.usageUrl = value;
    };

    const ignore = () => this.isRequestsAllowed || this.usageUrl != null;

    const createElementOriginal = document.createElement.bind(document);

    document.createElement = function createElementForTrackJS(...args) {
      const element = createElementOriginal(...args);

      if (ignore() || element.tagName.toUpperCase() !== 'IMG') {
        return element;
      }

      Object.defineProperty(element, 'src', {
        get() {
          return this.getAttribute('src');
        },
        set(value) {
          if (TrackJSUtil.URL_PATTERN.test(value)) {
            setUsageUrl(value);
          } else {
            this.setAttribute('src', value);
          }
        },
      });

      return element;
    };
  }

  /**
   * Callback for onError in TrackJS
   * @return {boolean}
   */
  onTrackJSError() {
    return this.isRequestsAllowed;
  }

  /**
   * Call it when requests are allowed
   */
  allow() {
    if (this.isRequestsAllowed) {
      return;
    }

    this.isRequestsAllowed = true;

    if (this.usageUrl == null) {
      return;
    }

    document.createElement('img').src = this.usageUrl;
  }
}

Usage:

import { TrackJS } from 'trackjs';

const util = new TrackJSUtil();

if (IS_CONSENT_GIVEN) {
  util.allow()
} else {
  callItWhenConsentGiven(() => {
    util.allow();
  });
}

util.install();

TrackJS.install({
  onError: () => util.onTrackJSError(),
});
Alexandr Vysotsky
  • 1,081
  • 13
  • 16
  • Interesting solution Alexandr! I'll look at including something like this to the agent. What if there was an API like: ``` TrackJS.install({ capture: false }); // after consent is gained TrackJS.enable(); // this would send usage and flush any cached errors ``` – Todd H. Gardner Oct 11 '19 at 15:12
  • Hi Todd, it will be great. I quickly wrote sample and tests for it if it what you mean it will solve our problem with GDPR. https://github.com/utlime/trackjs Don't forget about memory, need to limit amount of saved errors and clear references to prevent memory leaks. – Alexandr Vysotsky Oct 12 '19 at 17:49
  • Hey @ToddGardner, just to be sure that you read comment above. – Alexandr Vysotsky Oct 16 '19 at 05:52
  • 1
    Thanks Alexandr! This looks like a good solution, and we can probably add offline support as part of this. I have this added to our backlog and we'll get it planned out soon. – Todd H. Gardner Oct 17 '19 at 13:35