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

added support for sampling in ga and base adapter, fixed up some tests #1011

Merged
merged 6 commits into from
Apr 7, 2017

Conversation

snapwich
Copy link
Collaborator

@snapwich snapwich commented Feb 24, 2017

Type of change

  • Feature
  • Refactoring (no functional changes, no api changes)

Description of change

Added a new configuration property, sampling, to the google analytics adapter and the base analytics adapter which allows these adapters to only report a sampled percentage of visits. The sampling rate is set with a decimal value between zero and one, one (the default) being 100% of analytics sent, and zero being no analytics sent.

Also, while writing some unit tests for the base analytics adapter I was having issues with tests keeping state and affecting other tests (specifically my new tests), so I refactored the tests a bit to behave in a more isolated fashion. This also included adding a disableAnalytics method to the analytics adapter which allows for the cleanup of event listeners.

The sampling is used as an additional config like so:

pbjs.enableAnalytics({
    provider: 'ga',
    options: {
        global: 'ga',
        enableDistribution: false,
        sampling: .25
    }
});

That would allow for a 25% sampling rate in the analytics adapter.

Edit
Also added a new configuration property, pipe, to the base adapter. This option is a function you can provide to allow transformation of event data before it is logged.

});
window[config.global].restore();

it('SHOULD NOT call global again when adapter.enableAnalytics is called with previous timeout', () => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test originally said "WHEN adapter.enableAnalytics is called twice" and was testing that the event was present from the test that executed before it. I updated it to test what I think it was trying to test, but let me know if I'm mistaken.

@snapwich
Copy link
Collaborator Author

There was another feature we were hoping to add but it depended on a lot of this code that hasn't been merged yet, so I've updated this pull-request with that feature since it wasn't a big change. The original pull-request comment has been edited to describe the new "pipe" functionality.

@snapwich snapwich force-pushed the analytics-sampling branch from c377321 to 407d024 Compare March 15, 2017 20:37
@mkendall07
Copy link
Member

@snapwich
Thanks for the PR. Can you explain the use case for the "pipe" operation?

@snapwich
Copy link
Collaborator Author

@mkendall07 It allows publishers to transform data before being sent to an analytics adapter through runtime configuration. We'll be submitting our analytics adapter soon which more or less logs raw data, and allowing different data transformations for different accounts is a nice feature to have.

@bretg
Copy link
Collaborator

bretg commented Mar 16, 2017

@mkendall07 - Rich came up with the feature as a general way for each publisher to customize the latency or CPM buckets for logging to their analytics server.

I have Prebid.org documentation on my list for this amongst other recent updates...

@grevory
Copy link
Contributor

grevory commented Mar 16, 2017

👍

@bretg
Copy link
Collaborator

bretg commented Mar 20, 2017

@mjacobsonny or others - any opinions about whether sampling on BIDS_WON (renders) is a good idea in all cases? This PR currently samples everything at the same rate, but for publishers with high Direct sell-through, renders could be rare, so sampling aggressively may make the bids_won statistic log infrequently. Which could affect the ability to estimate revenue.

For other pubs, however, there may be many renders, so eliminating the sampling would cost them more in the analytics system. (GA has a monthly limit for the free account which would affect many pubs at 100% sampling).

One possible solution would be to pull bids_won out and allow it to have a separate sample rate. Doubt we really need to support a sample rate for every event, but bids_won is arguably different and may have different analytics requirements for different customers.

Don't want to over-complicate this, but still want to meet the goal of allowing pubs the option to control GA traffic.

@bretg
Copy link
Collaborator

bretg commented Mar 22, 2017

Spoke with one of our guys in the field who agreed that A) sampling would be helpful for some pubs, and B) renders could be different for some pubs.

So I'm proposing that we optionally allow a separate sampling rate on renders. e.g.

pbjs.que.push(function() {
    pbjs.enableAnalytics({
        provider: 'ga',
        options: {
            global: 'ga',
            enableDistribution: false,
            sampling: 0.05,
            renderSampling: 1
        }
    });
});

If renderSampling isn't specified, BIDS_WON events default to the sampling rate.

@protonate
Copy link
Collaborator

protonate commented Mar 27, 2017

I wonder if this change may be best scoped to individual analytics adapters that would work well with the sampling functionality. For example, current GA adapter doesn't extend AnalyticsAdapter, and the sampling and pipe changes are in AnalyticsAdapter. The AppNexus analytics adapter does extend AnalyticsAdapter but in this case sampling chance based on a coin flip is going to leave gaps in the analytics for an auction, as partial updates are packaged up with each Prebid event and then sent on a periodic basis.

@bretg
Copy link
Collaborator

bretg commented Mar 29, 2017

@protonate - good call on the AnalyticsAdapter issue.

in this case sampling chance based on a coin flip is going to leave gaps in the analytics for an auction

Rich and I discussed the coin flip happening at the page level, so all events on the page are either logged or not. So there shouldn't be gaps in the tracking for a given auction. Not what's there?

Also, I discussed the render-sampling idea with other people and am letting that one go.

@snapwich
Copy link
Collaborator Author

@protonate - with regards to sampling, the changes in this pull-request are included in both the GA adapter and the AnalyticsAdapter. With regards to the piping functionality, the change was just in the AnalyticsAdapter as the GA adapter handled each event separately. If you want, we could scope the piping functionality to our individual analytics adapter.

@snapwich snapwich force-pushed the analytics-sampling branch from eaece7b to 8fdfe47 Compare March 30, 2017 15:56
@snapwich
Copy link
Collaborator Author

I updated this pull-request to remove the piping functionality. We'll implement the desired interactions directly in our Rubicon analytics adapter. The sampling functionality should work in both GA and any adapter directed from the AnalyticsAdapter.

_enqueue.call(_this, { eventType, args });
}
});
if (_sampled) {
Copy link
Member

@mkendall07 mkendall07 Mar 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Edit: ignore this - I see how this work now.

Copy link
Collaborator

@protonate protonate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, confirmed functionality, tests are green, reviewed.

@protonate
Copy link
Collaborator

@snapwich @bretg this is reviewed so need one more from your end and we'll merge.

sendBidResponseToGa(bid);
utils._each(existingEvents, function (eventObj) {
var args = eventObj.args;
if (!eventObj) {
Copy link
Contributor

@grevory grevory Apr 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this validation is necessary then line 52 will throw a TypeError.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be noted that these line changes were only from moving existing code around to be inside the if(_sampled) { block above. However, this is a bug; and even though it existed before this pull-request, now is as good as time as any to fix it. Thanks!

Copy link
Contributor

@grevory grevory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One things needs review but otherwise +1

@@ -29,7 +29,6 @@ FEATURE: Analytics Adapters API
const adapter = new AnalyticsAdapter(config);
var spyTestGlobal = sinon.spy(window, config.global);

adaptermanager.registerAnalyticsAdapter(adapter, 'adapter');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI: I don't understand the consequences of removing this line or others like it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no consequence, which is why I removed them. All the unit tests were using the adapter instance directly rather than getting it from the adapters registered with Prebid.js. That's fine, but makes these registerAnalyticsAdapter lines irrelevant.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure it's all good. I was just pointing out my lack of extensive Prebid knowledge to know much about that is happening here.

bid = args;
sendBidResponseToGa(bid);
utils._each(existingEvents, function (eventObj) {
var args = eventObj.args;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could throw a TypeError. See comment below.

Copy link
Collaborator Author

@snapwich snapwich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grevory made updates!

@@ -29,7 +29,6 @@ FEATURE: Analytics Adapters API
const adapter = new AnalyticsAdapter(config);
var spyTestGlobal = sinon.spy(window, config.global);

adaptermanager.registerAnalyticsAdapter(adapter, 'adapter');
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no consequence, which is why I removed them. All the unit tests were using the adapter instance directly rather than getting it from the adapters registered with Prebid.js. That's fine, but makes these registerAnalyticsAdapter lines irrelevant.

sendBidResponseToGa(bid);
utils._each(existingEvents, function (eventObj) {
var args = eventObj.args;
if (!eventObj) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be noted that these line changes were only from moving existing code around to be inside the if(_sampled) { block above. However, this is a bug; and even though it existed before this pull-request, now is as good as time as any to fix it. Thanks!

@protonate protonate merged commit 2ace03f into prebid:master Apr 7, 2017
outoftime added a commit to Genius/Prebid.js that referenced this pull request Apr 19, 2017
…built

* 'master' of https://github.com/prebid/Prebid.js: (38 commits)
  Add optional domain parameter to AdButler adapter (prebid#1078)
  Send transactionID to Criteo Services (prebid#1113)
  Fix `buildMasterVideoTagFromAdserverTag()` not selecting winning bid (prebid#1106)
  Remove placement size selection and filtering (prebid#1107)
  revert `srcdoc` change (prebid#1130)
  Add new Adapter- Beachfront Media (prebid#1062)
  Fixes SpringServe adapter (prebid#1101)
  Update Widespace request param (prebid#1098)
  - New Adapter: Innity (prebid#1074)
  Update Roxot prebid analytic adapter (prebid#1034)
  Yarn Package Manager (prebid#1109)
  allow writing into current document if prebid is loaded inside an iframe (prebid#1066)
  Adapter bug fix (prebid#1096)
  fix typo
  added pr review process and governance model (prebid#1103)
  added support for sampling in ga and base adapter, fixed up some tests (prebid#1011)
  Add Inneractive adapter (prebid#1048)
  Add alias freewheel-ssp to stickyadstv bidder adapter  (prebid#1043)
  Add Facebook Audience Network adapter (prebid#1068)
  Add Atomx support (prebid#1056)
  ...
dluxemburg pushed a commit to Genius/Prebid.js that referenced this pull request Jul 17, 2018
prebid#1011)

* added support for sampling in ga and base adapter, fixed some tests

* added ability to pipe analytics events to customize values before logging

* don't mutate original args in analytics adapter pipe function

* remove pipe functionality in favor of custom adapter implementation

* fixed bug in GA adapter looking for property on potential non-object
@robertrmartinez robertrmartinez deleted the analytics-sampling branch July 5, 2023 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants