white-architect-17617
11/08/2023, 7:16 AMapplication_uuid (generated at the 2nd step, prior to the experiment start)
•
Implementation Details:
The application_uuid is created on the 2nd step, and I invoke the setAttributes function immediately to incorporate this UUID. The code snippet used is as follows:
await this.$growthbook.loadFeatures();
this.$growthbook.setAttributes({
...this.$growthbook.getAttributes(),
application_uuid: data.data.uuid,
});
For users who revisit, setAttributes is triggered on the mounted lifecycle hook.
Issue:
When I filter for "Experiment Started" events in Mixpanel, which are fired in the trackingCallback, it shows the actual number of users participating in the experiment. However, on the GrowthBook experiments page, the number of users is significantly lower.
Could there be a step I'm missing that would explain this discrepancy?
Has anyone else encountered a similar issue or can point me in the direction of what might be causing this?
Thank you in advance for your assistance!rhythmic-agent-34208
11/08/2023, 7:16 AMrhythmic-agent-34208
11/08/2023, 7:16 AMfresh-football-47124
fresh-football-47124
fresh-football-47124
white-architect-17617
11/08/2023, 10:02 AMrhythmic-agent-34208
11/09/2023, 1:32 AMrhythmic-agent-34208
11/14/2023, 11:58 PMwhite-architect-17617
11/16/2023, 1:01 PMfunction main() {
// Helper aggregation functions
const sum = (arr) => arr.reduce((sum, x) => sum + x, 0);
const count = (arr) => arr.length;
const countDistinct = (arr) => new Set(arr).size;
const min = (arr) => Math.min(...arr);
const max = (arr) => Math.max(...arr);
const avg = (arr) => count(arr)>0?(sum(arr)/count(arr)):0;
const percentile = (arr, p) => {
const s = [...arr].sort((a,b)=>a-b);
if(!s.length) return 0;
if(p<=0) return s[0];
if(p>=100) return s[arr.length-1];
const r = (s.length-1)*p/100;
const rf = Math.ceil(r) - r;
return s[Math.floor(r)]*rf + s[Math.ceil(r)]*(1-rf);
};
const median = (arr) => percentile(arr, 50);
// Experiment exposure event
function isExposureEvent(event) {
return event.name === "Experiment Started" && event.properties["Experiment Id"] === "technical_assessment_first" && event.time >= 1698173940000 && event.time <= 1700120128322;
}
// Application Submitted as FT
function isActivationMetric(event) {
return event.name === "Submit application" && event.properties["bookMeeting"]+'' == "true" && event.properties["bookCallOnly"]+'' == "false";
}
// Fast-track Flow Completed
function isMetric0(event) {
return event.name === "Application Step Completed" && event.properties["step_name"]+'' == "Fast-track Flow Completed";
}
return Events({
"from_date": "2023-10-24",
"to_date": "2023-11-16",
"event_selectors": [
{
"event": "Application Step Completed"
},
{
"event": "Submit application"
},
{
"event": "Experiment Started"
}
]
})
.filter(function(event) {
// Experiment exposure event
if(isExposureEvent(event)) return true;
// Application Submitted as FT
if(isActivationMetric(event)) return true;
// Fast-track Flow Completed
if(isMetric0(event)) return true;
// Otherwise, ignore the event
return false;
})
// Array of metric values for each user
.groupByUser(function(state, events) {
state = state || {
inExperiment: false,
multipleVariants: false,
activated: false,
start: null,
variation: null,
m0: [],
};
for(var i=0; i<events.length; i++) {
const event = events[i];
// User is put into the experiment
if(isExposureEvent(event)) {
if(!state.inExperiment) {
state.inExperiment = true;
state.variation = event.properties["Variant Id"];
continue;
}
else if(state.variation !== event.properties["Variant Id"]) {
state.multipleVariants = true;
continue;
}
else {
continue;
}
}
// Not in the experiment yet
if(!state.inExperiment) {
continue;
}
// Saw multiple variants so ignore
if(state.multipleVariants) {
continue;
}
// Not activated yet
if(!state.activated) {
// Does this event activate it? (Metric - Application Submitted as FT)
if(isActivationMetric(event)) {
state.activated = true;
state.start = event.time;
}
else {
continue;
}
}
// Metric - Fast-track Flow Completed
if(isMetric0(event) && event.time - state.start < 259200000) {
state.m0.push(1);
}
}
return state;
})
// Remove users that are not in the experiment
.filter(function(ev) {
if(!ev.value.inExperiment) return false;
if(ev.value.multipleVariants) return false;
if(ev.value.variation === null || ev.value.variation === undefined) return false;
if(!ev.value.activated) return false;
return true;
})
// Aggregate the metric value arrays for each user
.map(function(user) {
// Metric - Fast-track Flow Completed
user.value.m0 = user.value.m0.length ? 1 : 0;
return user;
})
// One group per experiment variation with summary data
.groupBy(["value.variation"], [
// Total users in the group
mixpanel.reducer.count(),
// Metric - Fast-track Flow Completed
mixpanel.reducer.numeric_summary('value.m0'),
])
// Convert to an object that's easier to work with
.map(row => {
const ret = {
variation: row.key[0],
dimension: '',
users: row.value[0],
metrics: [],
};
const metricIds = [
// Fast-track Flow Completed
"met_405opf1mlncw1a93"
];
const metricTypes = [
"binomial"
];
for(let i=1; i<row.value.length; i++) {
ret.metrics.push({
id: metricIds[i-1],
metric_type: metricTypes[i-1],
count: row.value[i].count,
main_sum: row.value[i].sum,
main_sum_squares: row.value[i].sum_squares,
});
}
return ret;
});
}rhythmic-agent-34208
11/16/2023, 8:32 PMwhite-architect-17617
11/17/2023, 4:49 AMrhythmic-agent-34208
11/20/2023, 5:40 PM