```{ "users": 0 }```
# ask-questions
p
Copy code
{
  "users": 0
}
f
What does the JQL look like when you view queries?
p
hey @future-teacher-7046
Copy code
function main() {
  // Site-Wide - Number of Users
  return Events({from_date: "2021-05-11", to_date: "2021-08-09"})
  .filter(function(event) {
    // Valid page view
    if(event.name === "Page view") return true;
    return false;
  })
  // One event per user
  .groupByUser(mixpanel.reducer.min("time"))
  .reduce([
    // Overall count of users
    mixpanel.reducer.count(),
    // Count of users per day
    (prevs, events) => {
      const dates = {};
      prevs.forEach(prev => {
        prev.dates.forEach(d=>dates[d.date] = (dates[d.date] || 0) + d.users)
      });
      events.forEach(e=>{
        const date = (new Date(e.value)).toISOString().substr(0,10);
        dates[date] = (dates[date] || 0) + 1;
      });
      return {
        type: "byDate",
        dates: Object.keys(dates).map(d => ({
          date: d,
          users: dates[d]
        }))
      };
    }
  ])
  // Transform into easy-to-use objects
  .map(vals => vals.map(val => !val.type ? {type:"overall",users:val} : val))
}
click to minimize
the second query looks like its checking for the right thing at least
Copy code
function main() {
  // Site-Wide - Metric value (appointment_booked)
  return Events({from_date: "2021-05-11", to_date: "2021-08-09"})
  .filter(function(event) {
    // Valid page view
    if(event.name === "Page view") return true;
    if(event.name === "appointment_booked") return true;
    return false;
  })
  // Metric value per user
  .groupByUser(function(state, events) {
    state = state || {firstPageView: false, metricValue: null, queuedValues: []};
    for(var i=0; i<events.length; i++) {
      if(!state.firstPageView && events[i].name === "Page view") {
        state.firstPageView = events[i].time;
        // Process queued values
        state.queuedValues.forEach((q) => {
          // Check conversion window (3 days)
          if(q.time - state.firstPageView > 259200000) {
            return
          }
          state.metricValue = Math.min(1,(state.metricValue || 0) + q.value);
        });
        state.queuedValues = [];
        continue;
      }
      if(events[i].name === "appointment_booked") {
        if(!state.firstPageView) {
          continue;
        }
        // Check conversion window (3 days)
        if(events[i].time - state.firstPageView > 259200000) {
          continue;
        }
        state.metricValue = Math.min(1,(state.metricValue || 0) + 1);
      }
    }
    return state;
  })
  // Remove users that did not convert
  .filter(function(ev) {
    return ev.value.firstPageView && ev.value.metricValue !== null;
  })
  .reduce([
    // Overall summary metrics
    mixpanel.reducer.numeric_summary('value.metricValue'),
    // Summary metrics by date
    (prevs, events) => {
      const dates = {};
      prevs.forEach(prev => {
        prev.dates.forEach(d=>{
          dates[d.date] = dates[d.date] || {count:0, sum:0};
          dates[d.date].count += d.count;
          dates[d.date].sum += d.sum;
        })
      });
      events.forEach(e=>{
        const date = (new Date(e.value.firstPageView)).toISOString().substr(0,10);
        dates[date] = dates[date] || {count:0, sum:0};
        dates[date].count++;
        dates[date].sum += e.value.metricValue;
      });
      return {
        type: "byDate",
        dates: Object.keys(dates).map(d => ({
          date: d,
          ...dates[d]
        }))
      };
    }
  ])
  // Transform into easy-to-use objects
  .map(vals => vals.map(val => {
    if(val[0] && val[0].percentile) return {type: "percentile",percentiles:val};
    if(val.count) return {type: "overall", ...val};
    return val;
  }));
}
f
Mixpanel does not track page views by default. Are you tracking a "Page view" event in your app?
p
Ah - does it have to be page views @future-teacher-7046? I don't want to track page views, I have an event thats being fired from the front-end called
appointment_booked
well, I have lots of events - but thats the one I'm worried about for now!
f
In order to calculate conversion rates, growth book needs both the metric value (appointment_booked) and the number of users. In an experiment, the number of users comes from a "viewed experiment" (or similar) event that you would add. On the metric page itself, it shows the site-wide conversion rate, so it needs an event fired on every page view to get the number of users. If you don't care about the site-wide conversion rate, you can safely ignore the error. You will still be able to use the metric in an experiment.
p
ahhhhhhhhh
ok, that makes sense