Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable tracking and still be able to buffer events #1410

Open
marcin-j opened this issue Feb 11, 2025 · 2 comments
Open

Disable tracking and still be able to buffer events #1410

marcin-j opened this issue Feb 11, 2025 · 2 comments
Labels
type:enhancement New features or improvements to existing features.

Comments

@marcin-j
Copy link
Contributor

Is your feature request related to a problem? Please describe.
1st use case:
I want to be able to disable tracking, but still buffer events in the events store. Our use case is that we want to call an async endpoint before starting tracking to decide, if we are allowed to track or not (not related to the consent cookies, and needs to be an async call).

2nd use case:
Be able to disable tracking, without setting the opt-out cookie.

3rd use case:
Be able to globally filter out unwanted query parameters in all URLs that we send to the collector endpoint, link clicks, custom events, page views etc.

Describe the solution you'd like
Allow us to override/extend Emmiter, EmmiterRequest, EmitterEvent.

We could modify the dictionaries returned from getPayload methods, we could intercept all requests made by the emmiter and we could disable tracking without having to set up the opt-out cookies.

Describe alternatives you've considered
We came up with a workaround where we use our own event store - when tracker calls the async iterator , we intercept it with our async request and then return an empty iterator or the default one, depends if we are allowed to track or not. Thing is that this solution is hacky, and additionally we would need to handle situations where event skips the event store.

@marcin-j marcin-j added the type:enhancement New features or improvements to existing features. label Feb 11, 2025
@jethron
Copy link
Contributor

jethron commented Feb 12, 2025

Most of these should be possible in v4 with a bit of work using the current APIs.

1st use case:
I want to be able to disable tracking, but still buffer events in the events store. Our use case is that we want to call an async endpoint before starting tracking to decide, if we are allowed to track or not (not related to the consent cookies, and needs to be an async call).

Not great but possible with customFetch:

const {promise: haveConsent, resolve} = Promise.withResolvers(); // call resolve when you have consent

snowplow('newTracker', 'cfetch', 'collector.example.com', {
  customFetch: (req) => Promise.race([
    haveConsent, // if we have consent will resolve immediately
    new Promise((_, rej) => req.signal.addEventListener("abort", rej)), // don't leak waiting for timeout, usually ~5 seconds
  ]).then(() => fetch(req)), // requests will likely timeout and remain in-queue until consent is obtained
});

checkMyConsentEndpoint().then(resolve).then(() => {
  snowplow('flushBuffer:cfetch); // flush buffers to send any pending requests that have timed out, rather than waiting for next event to be tracked
});

2nd use case:
Be able to disable tracking, without setting the opt-out cookie.

A custom plugin's filter should work as long as you can check the consent synchronously at time of send (e.g. an inline plugin) that just returns false if you know you don't have consent; you can add plugins at pretty much any time.

let iHaveConsent = true;
const filterPlugin = {
  FilterAllPlugin: function () {
    return {
      filter: () => {
        return iHaveConsent;
      },
    };
  },
};
snowplow('addPlugin', filterPlugin, 'FilterAllPlugin');
// we have consent, events will track as usual

// events from resolution of checkConsent onwards will be dropped and removed from storage immediately if resolved updatedConsent is false, until you toggle iHaveConsent back to true
checkConsent().then((updatedConsent) => iHaveConsent = updatedConsent); 

3rd use case:
Be able to globally filter out unwanted query parameters in all URLs that we send to the collector endpoint, link clicks, custom events, page views etc.

"Globally" is the hard part here, because you can't easily know which custom event/entity properties are URLs you need to be doing this on. Apart from that, again, a custom inline plugin with a beforeTrack can inspect/modify the payload and should work for this purpose if you're OK with some generic solution (with perhaps some deny list to control false positives).

@marcin-j
Copy link
Contributor Author

Thanks Jethro, your suggestions look promising. I'll try it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:enhancement New features or improvements to existing features.
Projects
None yet
Development

No branches or pull requests

2 participants