Reference
What the numbers mean
This page defines every number and every dimension that misomoon reports, as the code
computes them. The dashboard, the Stats API, and the MCP tools call the same functions in
apps/api/src/stats.ts, which build their SQL in
packages/core/src/queries.ts, so one number means the
same thing everywhere. The API reference lists the parameters and response
fields. Use the dashboard shows where each number appears.
Headline metrics
The KPI tiles, GET /api/v1/stats/aggregate, and every point of
GET /api/v1/stats/timeseries return these nine metrics. A metric read from events counts
the events whose time falls in the period. A metric read from visits counts the visits
that started in the period.
| Dashboard tile | API name | Read from | Definition | Unit |
|---|---|---|---|---|
| People | visitors | Events | Distinct visitor ids among the pageviews and custom events. Engagement pings don't count, and neither do payments without a visit on their UTC day. | Count |
| Visits | visits | Visits | Visits that started in the period. | Count |
| Pageviews | pageviews | Events | pageview events. | Count |
| Pages per visit | views_per_visit | Visits | The pageviews of the visits that started in the period, divided by visits. | Rounded to 2 decimals |
| Left at once | bounce_rate | Visits | Bounced visits as a percent of visits. Bounces has the rule. | Percent, 1 decimal |
| Time per visit | visit_duration | Visits | Summed visit durations divided by visits. Visit duration and time on page has the rule. | Whole seconds |
| None | events | Events | Every event that is not a pageview or an engagement: custom events, the events the tracker sends by itself, and Payment and Refund events. Events sent with interactive: false count here too. | Count |
| Revenue | revenue | Events | The sum of the amounts on events, net of refunds, in the site's currency. | Site currency, 2 decimals |
| None | average_revenue | Events | revenue divided by the number of events with an amount above zero. Refunds don't count in that number. | Site currency, 2 decimals |
pageviews and views_per_visit can disagree. pageviews counts views by their own
time, and views_per_visit counts the views of visits that started in the period, even
when a view happened after the period ended.
Each site has one reporting currency, USD unless you set another. revenue and
average_revenue count the events in that currency and the events sent without a
currency. They never add up amounts in different currencies. The amount on a tracker or
SDK event is kept between 0 and 1,000,000,000. Refunds come from payment webhooks as
negative amounts. Connect payments explains how a payment finds its visit.
Compare with an earlier period
With compare=previous the comparison period is the stretch of the same length right
before the current one. With compare=year it is the same dates a year earlier. change
holds one value per metric:
| Metric | change |
|---|---|
bounce_rate | The difference in percentage points, rounded to 1 decimal. |
| Every other metric | The percent change from the earlier period, rounded to 1 decimal. It is 0 when both periods are 0, and null when only the earlier period is 0. |
A visitor id lasts one UTC day
misomoon sets no cookies and stores nothing on the device. To count people, the Worker
hashes a random salt, the site id, the IP address, and the user agent with SHA-256, and
keeps the first 16 hex characters as visitor_id (visitorId in
packages/core/src/ingest.ts). Each UTC day has its
own salt. The Worker makes it on first use and keeps it in the salts table of
CONTROL. The hourly maintenance job deletes salts that are more than two days old.
The IP address is never stored.
These rules follow from the daily salt:
- The same person gets a new id at 00:00 UTC. A visitor count over several days is the
sum of each UTC day's unique visitors. Someone who visits on 5 days of a month counts
5 times in that month's
visitors. - The salt rotates at 00:00 UTC, not at the site's local midnight. A local day, a
todayperiod, or a24hperiod that spans 00:00 UTC can count one person twice. - Two people behind one IP address with the same user agent share an id that day. One person on two devices, or with two browsers, has two ids.
- Breakdown rows, funnels, paths, and page interaction reports count visitors by the same id.
Why is a visitor unique only for one day? gives the short answer.
Unique counts add up across shards
A site's data lives in ranges of whole UTC days, one shard per range
(Sharding). A day never spans two shards, and an id never
lasts past its day, so no visitor appears on two shards. misomoon counts distinct
visitors on each shard and adds the counts. For a rate such as bounce_rate, it adds the
numerators and the denominators of every shard first and divides once. It never averages
a rate across shards.
A visit ends after 30 minutes without activity
A visit, called a session in the code, is a run of events from one visitor id. The
Worker assigns each event to a visit in assignSessions in
packages/core/src/ingest.ts, with SESSION_GAP set to
30 minutes:
| Rule | Effect |
|---|---|
| An event comes within 30 minutes of the visit's last activity | It joins that visit. Engagement pings count as activity, so a visitor who reads one page for an hour keeps one visit. |
| An event comes more than 30 minutes after the last activity | A pageview or a custom event starts a new visit. An engagement ping is dropped. |
| A visit is open at 00:00 UTC | In the first 30 minutes of a UTC day the Worker also computes the visitor's id under yesterday's salt, so the visit carries on. Each event keeps its own day's id. If the site moved to another shard at that midnight, the visit splits in two. |
| A later event in the visit has a new referrer or new UTM tags | It stays in the visit and takes the visit's source, channel, referrer, and UTM values. A new campaign doesn't start a new visit. |
A visit takes its source, channel, referrer, UTM tags, hostname, location, browser, operating system, device, screen, and language from its first event, and keeps them. Reports read these columns of the visit, which the Worker updates as events arrive:
| Column | Meaning |
|---|---|
entry_path | The path of the visit's first event. The entry_page dimension reads it. |
exit_path | The path of the visit's latest pageview. The exit_page dimension reads it. |
pageviews | The visit's pageviews. |
events | The visit's interactive custom events, which is all that bounce rate needs. |
duration_ms | The time from the first event to the latest pageview or custom event. |
Payments never change a visit. A Payment or Refund row joins the visit's visitor id
only when the payment comes on the UTC day of the visit. Otherwise its visitor_id is
empty and no visitor count includes it.
A bounce is a visit with one pageview and no interaction
A visit is a bounce when it has at most one pageview and no interactive custom event.
The SQL test is pageviews <= 1 AND events = 0 on the visit's row.
| Event in the visit | Ends the bounce |
|---|---|
A second pageview | Yes |
| A custom event | Yes |
A custom event sent with interactive: false (i: false on the beacon) | No |
Outbound link, Download, Form sent, or 404 from the tracker | Yes, always. interactive: false has no effect on them. |
engagement (engaged time, scroll, Web Vitals, clicks) | No |
Payment or Refund from a webhook | No |
Under a page filter, bounce rate counts only the visits that entered on a matching page,
in the numerator and in the denominator. A page row in a breakdown takes its bounce rate
from the visits that entered on that page.
Imported history from Google has no bounces, so misomoon counts a session that Google didn't mark as engaged as a bounce.
Visit duration and time on page measure different things
Visit duration (visit_duration) | Time on page (time_on_page) | |
|---|---|---|
| Where it shows | KPI tiles, and breakdown rows of visit dimensions, pages, and goals | Page breakdown rows |
| Measured from | The visit's events | The engagement pings of each page |
| What counts | The time from the visit's first event to its latest pageview or custom event | Engaged time: the time the page is shown and the browser window has focus |
| Engagement pings | Keep the visit open, but don't make it longer | Carry the time |
| A visit with one pageview | Lasts 0 seconds | Has the engaged time it sent |
| Average over | Every visit in the scope, bounces included | Each visit that sent engaged time for the page |
| Unit | Whole seconds | Whole seconds |
m.js sends an engagement ping when the page is hidden or the route changes. It doesn't
send one for under one second of engaged time, unless a feature, such as clicks or Web
Vitals, has data to send. The Worker keeps at most 6 hours of engaged time per ping. A
visit that opens the same page twice adds the engaged time of both views. Time on page
divides the summed time of each page by the number of visits that sent time for it.
Scroll depth is the deepest point of each visit
The tracker records the lowest point of the page that came into view: the scroll position plus the window height, as a percent of the page height. The Worker keeps it between 0 and 100 and rounds it to a whole number. A page that fits in the window reports 100.
| Where | Value |
|---|---|
scroll_depth on a page row | The average of each visit's deepest scroll on that page, as a whole percent. |
The Scroll report, average | The same average for the pages in scope. |
The Scroll report, reached | For each depth 0, 10, and up to 100, the visits whose deepest scroll is at least that depth, and their share of all visits that sent a scroll depth. |
Scroll depth is always on. It needs no feature box.
Breakdown rows
GET /api/v1/stats/breakdown?property=<name> returns one row per value. Each row has
key, visitors, visits, pageviews, events, bounce_rate, and visit_duration.
What those fields count depends on the kind of property:
| Property | visitors | visits | pageviews | Extra fields |
|---|---|---|---|---|
A visit dimension, such as source or country | Distinct visitor ids of the visits that started in the period with this value | Visits with this value | Pageviews of those visits | revenue and average_revenue when a row has revenue |
entry_page | The same, for visits that entered on the page | Visits that entered on the page | Pageviews of those visits | None |
exit_page | The same, for visits that ended on the page | Visits that ended on the page | Pageviews of those visits | exit_rate |
page | Distinct visitors with a pageview of the page | Visits that entered on the page | Pageviews of the page | time_on_page, scroll_depth |
event | Distinct visitors who sent the event | 0 | 0 | conversion_rate, revenue, average_revenue |
prop:<key> and props | Distinct visitors with an event that carries the value | 0 | Pageviews that carry the value | conversion_rate, revenue, average_revenue |
goal | Distinct visitors who reached the goal | Visits that match the goal | Pageviews that match the goal | kind, match, conversion_rate, revenue, average_revenue |
bounce_rate and visit_duration on a row follow the rules for the headline metrics,
over the row's visits. On a page row they describe the visits that entered on that page.
| Field | Definition | Unit |
|---|---|---|
exit_rate | Visits that ended on the page, divided by the page's pageviews in the period. The pageviews ignore any exit_page filter. At most 100. null when the page has no pageviews in the period. | Percent, 1 decimal |
conversion_rate | The row's visitors divided by the visitors of the period. Those visitors follow every filter except goal, event, and prop: filters. | Percent, 1 decimal |
revenue | Net revenue of the row's events, in the site's currency. On a visit dimension, it comes from the events with an amount that carry the value. A payment carries its visit's values, so a renewal counts toward the source of its visit even when that source had no visit in the period. | Site currency, 2 decimals |
average_revenue | revenue divided by the row's events with an amount above zero. | Site currency, 2 decimals |
These rules hold for every breakdown:
- A row with no value has the key
(none). The dashboard shows it as Direct / none forsourceandreferrer, (not set) for the UTM dimensions, and Unknown for the rest. - Rows sort by
visitors, then bypageviews, then by key. - Each shard returns its top 500 values. When one shard reached that cap, the response
has
truncated: true, and rare values may be missing. limittakes 1 to 200 rows, andhas_moresays whether another page exists.searchkeeps the values that contain the text. The search runs on each shard, so it finds values outside the top 500.
Goals count visitors who reached them
A goal is an event name or a page path. Its row counts the visitors who sent the event or
had a pageview or custom event on a matching page. For a page goal, events is the
number of matching pageviews, and revenue is 0. Only event goals carry revenue.
goal==<name> as a filter turns into the goal's event or page filter.
Goal rows read only the events misomoon collected. In a report without filters, the
visitors that conversion_rate divides by include imported history, so the rate reads
lower over a period with imported days. Conversion rate
and Matching rules have the details.
Web Vitals
GET /api/v1/stats/vitals and Speed report five Web Vitals from real visits. They
need the Web Vitals (vitals) feature
(Choose what to track).
| Vital | API name | Measures | Unit | Good | Poor |
|---|---|---|---|---|---|
| Largest Contentful Paint | lcp | The start time of the largest element painted | ms | 2,500 or less | Over 4,000 |
| Interaction to Next Paint | inp | The 98th percentile of the page's interaction durations, counting interactions of 16 ms or more | ms | 200 or less | Over 500 |
| Cumulative Layout Shift | cls | The largest burst of layout shifts that come within 1 second of each other, up to 5 seconds long. Shifts right after user input don't count. | Score, 3 decimals | 0.1 or less | Over 0.25 |
| First Contentful Paint | fcp | The time of the first paint of text or an image | ms | 1,800 or less | Over 3,000 |
| Time to First Byte | ttfb | The navigation's responseStart | ms | 800 or less | Over 1,800 |
A value is good at or under the good limit, poor over the poor limit, and
needs_improvement in between. samples is the number of values.
The tracker sends one set of values per page load, with the page's first engagement ping. Route changes in a single-page app send none, and a vital the browser didn't measure is left out. The Worker keeps times between 0 and 60,000 ms and CLS between 0 and 10.
p75 is the 75th percentile, read from a histogram that every shard fills:
| Vital | Bin width | Values that share the last bin |
|---|---|---|
lcp | 50 ms | 20,000 ms or more |
inp | 8 ms | 2,000 ms or more |
cls | 0.005 | 10 |
fcp | 50 ms | 20,000 ms or more |
ttfb | 25 ms | 10,000 ms or more |
misomoon adds the bins of every shard, finds the bin where three quarters of the values
are reached, and reports the middle of that bin. p75 is null without samples. The
dashboard rates a tile by its p75 with the limits above.
Channels
classify in packages/core/src/channel.ts gives each
visit one of 11 channels. It reads the visit's first event: the referrer host, the UTM
tags, and the page URL. The rules run in this order, and the first rule that matches
wins:
| Order | Channel | Rule |
|---|---|---|
| 1 | AI Assistants | The referrer is a known AI assistant, or utm_source contains chatgpt, openai, perplexity, claude, gemini, or copilot, in any case. |
| 2 | Email | utm_medium is email or newsletter, or the referrer is a known webmail host. |
| 3 | Affiliates | utm_medium is affiliate. |
| 4 | Display | utm_medium is display, banner, or interstitial. |
| 5 | Paid Search or Organic Search | The referrer is a known search engine, or utm_medium contains search. It is Paid Search when the visit has a paid signal. |
| 6 | Paid Social or Organic Social | The referrer is a known social site, or utm_medium is social, sm, socialmedia, social-media, social_media, social media, or the same forms with network. It is Paid Social when the visit has a paid signal. |
| 7 | Video | The referrer is a known video site, or utm_medium is video. |
| 8 | Paid Search | The visit has a paid signal and no rule above matched. |
| 9 | Referral | The visit has a referrer host or a utm_source. |
| 10 | Direct | Nothing above matched. |
utm_medium is compared in lower case. A visit has a paid signal when its page URL has a
gclid or msclkid parameter, or utm_medium is cpc, ppc, paidsearch,
paid_search, cpm, cpv, or cpa, or starts with paid.
Sources and referrers
The referrer dimension is the host of document.referrer, with a leading www. and
then a leading m. removed. A referrer from the page's own host, compared without www.,
is no referrer, so moving between pages of the site is never a referral. A link from
another subdomain of your site is a referral.
The source dimension is the first of these that has a value:
- The name of a known referrer host, from the table below.
utm_source, tidied. A value equal to the first part of a known host takes that source's name, sogooglebecomesGoogle. Other values of 3 characters or fewer become upper case, and longer values get a capital first letter.- The referrer host.
Direct.
utm_source reads the utm_source parameter of the landing URL, then ref, then
source. A known referrer wins over utm_source. An unknown referrer loses to it, and
the referrer dimension still holds the host.
Hosts without a trailing dot match the host itself and its subdomains. Hosts with a
trailing dot, such as google., match any host that starts with it or contains it after a
dot, such as google.de and google.co.uk. Exact hosts are checked first, so
gemini.google.com is Gemini and mail.google.com is Gmail.
| Kind | Source names and hosts |
|---|---|
| Search | Google (google.), Bing (bing.com), DuckDuckGo (duckduckgo.com), Yahoo (search.yahoo.), Yandex (yandex.), Baidu (baidu.com), Ecosia (ecosia.org), Brave Search (search.brave.com), Naver (naver.com), Kagi (kagi.com) |
| AI assistant | ChatGPT (chatgpt.com, chat.openai.com), Perplexity (perplexity.ai), Claude (claude.ai), Gemini (gemini.google.com), Copilot (copilot.microsoft.com), DeepSeek (chat.deepseek.com), You.com (you.com), Phind (phind.com), Meta AI (meta.ai), Grok (grok.com) |
| Social | X (t.co, x.com, twitter.com), Facebook (facebook.com, fb.me), Instagram (instagram.com), LinkedIn (linkedin.com, lnkd.in), Reddit (reddit.com), Threads (threads.net), Bluesky (bsky.app), Hacker News (news.ycombinator.com), Pinterest (pinterest.), TikTok (tiktok.com), Product Hunt (producthunt.com), Mastodon (mastodon.), Discord (discord.com), GitHub (github.com) |
| Video | YouTube (youtube.com, youtu.be), Vimeo (vimeo.com), Twitch (twitch.tv) |
| Webmail | Gmail (mail.google.com), Outlook (outlook.live.com), Yahoo Mail (mail.yahoo.com) |
misomoon also stores the referrer URL without its query string. No report breaks it down.
Dimensions
Every breakdown and filter takes one of these 26 dimensions
(DIMENSIONS in packages/core/src/filters.ts).
GET /api/v1/meta/dimensions returns them with their labels. The label is what the
dashboard's filter bar shows.
Each dimension has a scope. An event dimension is a value of each event. A visit dimension is stored on the visit and on each of its events. An entry or exit dimension exists only on the visit. A visit matches an event filter when any of its events match, and an event matches an entry or exit filter when its visit does.
| API name | Label | Scope | Meaning |
|---|---|---|---|
page | Page | Event | The page path, without the query string and without a trailing slash, except for /. A hash route (#/pricing or #!/pricing) is part of the path. A path part that looks like an email address becomes :email, and a part of 20 or more mixed letters and digits becomes :token. Up to 500 characters. |
entry_page | Entry page | Entry or exit | The path of the visit's first event. |
exit_page | Exit page | Entry or exit | The path of the visit's latest pageview. |
hostname | Hostname | Visit | The page's host, without www.. Always the site's domain or a subdomain of it. |
event | Event | Event | The event name: pageview, engagement, a custom name, a built-in event, Payment, or Refund. The event breakdown lists only custom, built-in, and payment events. |
source | Source | Visit | Where the visit came from, by the rules in Sources and referrers. |
referrer | Referrer | Visit | The referrer host. |
channel | Channel | Visit | One of the 11 channels. |
utm_source | UTM source | Visit | The utm_source parameter of the landing URL, else ref, else source. Up to 200 characters. |
utm_medium | UTM medium | Visit | The utm_medium parameter of the landing URL. Up to 200 characters. |
utm_campaign | UTM campaign | Visit | The utm_campaign parameter of the landing URL. Up to 200 characters. |
utm_term | UTM term | Visit | The utm_term parameter of the landing URL. Up to 200 characters. |
utm_content | UTM content | Visit | The utm_content parameter of the landing URL. Up to 200 characters. |
country | Country | Visit | The two-letter ISO 3166-1 country code from Cloudflare. The dashboard shows the country's name. |
region | Region | Visit | The region name from Cloudflare. |
city | City | Visit | The city name from Cloudflare. |
continent | Continent | Visit | The two-letter continent code from Cloudflare. |
timezone | Timezone | Visit | The visitor's IANA time zone from Cloudflare. It is not the site's time zone. |
network | Network | Visit | The name of the organization that runs the visitor's network (the AS organization). |
browser | Browser | Visit | The browser from the user agent: Edge, Opera, Samsung Internet, Yandex, Vivaldi, Brave, DuckDuckGo, Arc, Facebook, Instagram, Line, Firefox, Chrome, Safari, or Unknown. For an app that uses the SDK, the app's name. |
browser_version | Browser version | Visit | The browser and its major version, such as Chrome 141. |
os | OS | Visit | Windows, iOS, Android, ChromeOS, macOS, Linux, or Unknown. |
os_version | OS version | Visit | The operating system and the first two numbers of its version, such as iOS 17.4 or macOS 10.15. Windows NT 10.0 shows as Windows 10/11. |
device | Device | Visit | Desktop, Mobile, or Tablet, from the user agent. |
screen | Screen | Visit | The screen width as a class: Mobile under 576 pixels, Tablet under 992, Laptop under 1,440, and Desktop from 1,440. |
language | Language | Visit | The first language tag from the SDK's beacon or, for m.js, from the request's Accept-Language header, such as en-US. Up to 16 characters. |
These names work in some places only:
| Name | Where | Meaning |
|---|---|---|
prop:<key> | Breakdowns and filters | The value of one custom property. A key is 1 to 64 letters, digits, _, ., or -. An event keeps up to 30 properties, and a text value keeps its first 300 characters. |
goal | Breakdowns and filters | A breakdown lists every goal. A filter takes goal names and becomes the goal's event or page filter. One filter can't mix page goals and event goals. |
props | Breakdowns | Every custom property at once, as key: value rows. |
search_term | Breakdowns | Google searches that led to the site, read live from Google Search Console. See Search terms. |
A filter value of (none) matches events or visits without a value.
Filters has the operators and limits.
Other reports
Live
GET /api/v1/stats/realtime and Live ignore the period and apply the filters.
| Field | Definition |
|---|---|
visitors | Distinct visitors with a pageview or custom event in the last 5 minutes. |
pageviews | Pageviews in the last 5 minutes. |
minutes | For each minute from 30 minutes ago to the current minute, its pageviews and distinct visitors. |
pages, sources, countries | The top 8 of each in the last 5 minutes, by distinct visitors. |
feed | The latest 40 events of the last 30 minutes, engagement pings left out. |
Each window runs one minute past the current time, so an event from a browser whose clock runs a little fast still shows.
Funnels and paths
A funnel step counts the visitors who reached it, and conversion is that count as a
percent of the first step's visitors, to 1 decimal. dropoff is the previous step's
visitors minus this step's, and never below 0. entered counts the distinct visitors with
a pageview or custom event in the period. A visitor id lasts one UTC day, so a visitor's
steps must happen on one UTC day. Paths count pageviews in visit order, with reloads of
the same page folded into one, and each row's share is a percent of the visitors who
followed the path. Funnel modes and
Paths have the rules.
Page interactions
GET /api/v1/stats/behavior reads the counts that engagement pings carry. Every count on a
ping is the change since the previous ping, so the sums are exact.
| Report | Field | Definition |
|---|---|---|
clicks | clicks, rage, dead | Clicks, rage clicks, and dead clicks, summed per element and page |
clicks | pageviews, visitors | Pageviews and distinct visitors of the pages in scope, to divide the clicks by |
scroll | visits, average, reached | See Scroll depth |
search | searches | Pageviews with a site search term |
search | visitors, total_visitors | Visitors who searched, and every visitor in scope |
errors | count, last_seen | Times an error happened, and when it last did |
forms | starts, submissions | Page views where someone started the form, and submissions |
forms | conversion | submissions divided by starts, as a percent, at most 100 |
forms | interactions, dropoffs | Per field: page views that focused it, and page views that left the form at it without a submit |
media | plays, reached | Plays, and the percent of plays that reached 25%, 50%, 75%, and the end (95%) |
content | impressions, clicks, ctr | Times tagged content was seen and clicked, and clicks as a percent of impressions, at most 100 |
Each report's visitors counts distinct visitors per row, such as the visitors who hit an
error. See what people do on a page says what
the tracker collects for each report.
Search terms come from Google
The search_term breakdown asks Google Search Console for the period when you request it,
and caches the answer for ten minutes. Its numbers come from Google, so they cover only
the days Google has processed, usually up to two or three days ago.
| Field | Definition |
|---|---|
clicks | Clicks from Google search. The row's visitors repeats it. |
impressions | Times the site appeared in Google results for the query |
ctr | Clicks as a percent of impressions, 1 decimal |
position | The average position in the results, 1 decimal. 1 is the top. |
Google can filter only by page and device. source==Google and
channel==Organic Search change nothing, because every row is Google search traffic. Any
other filter returns 400.
Periods follow the site's time zone
Each site has an IANA time zone. An unknown zone name falls back to UTC. misomoon looks up
the zone's offset for each instant, so a day starts at local midnight on both sides of a
daylight saving change (time.ts in
packages/core/src/time.ts).
period | Window | Default interval |
|---|---|---|
realtime | The last 30 minutes | minute |
today | Local midnight until now | hour |
yesterday | The local day before today | hour |
24h | The last 24 hours | hour |
7d | Today and the 6 local days before it | day |
28d | Today and the 27 local days before it | day |
30d | Today and the 29 local days before it. The default period. | day |
90d | Today and the 89 local days before it | day |
mtd | The first of this month until now | day |
lastmonth | The whole of last month | day |
ytd | January 1 until now | week |
6mo | This month and the 5 months before it | month |
12mo | This month and the 11 months before it | month |
all | Local midnight of the site's first visit, or of the day the site was added when that is earlier, until now | By length |
custom | from to to, both whole local days, at most 400 days | By length |
A period that ends now runs one minute past the current time. A custom period ends at
that point too when to is today.
The default interval for all and custom depends on the period's length:
| Length | Interval |
|---|---|
| Up to 2 hours | minute |
| Up to 3 days | hour |
| Up to 120 days | day |
| Up to 400 days | week |
| Longer | month |
interval picks another interval. Minute buckets start on UTC minutes. Hour buckets
start on local hours. Day buckets start at local midnight, week buckets on Monday at
local midnight, and month buckets on the first of the month at local midnight. A series
holds at most 1,500 buckets. A longer series returns 400 with the number of buckets and
asks for a coarser interval. Buckets without data come back as zeros.
Imported history joins unfiltered reports
History imported from Google or from CSV files lands in each shard's imported table as
daily totals per dimension and value
(packages/core/src/imported.ts). misomoon adds it to
a report only when the report has no filters. imported=0 leaves it out. Bring your
history shows how to import.
| Report | Uses imported history |
|---|---|
| Headline metrics and the time series | Yes. A day lands in the bucket of its local midnight, so minute and hour charts show it at midnight. |
| Breakdowns of the dimensions in the next table | Yes |
| Goal rows | No. The visitors that conversion_rate divides by include imported visitors. |
| Revenue, Web Vitals, live, funnels, paths, page interactions, and other dimensions | No |
Imported visitors are each day's unique visitors, so adding days matches how misomoon counts its own visitors.
| Dimension | From a CSV export | From Google |
|---|---|---|
channel | Derived from the source and UTM tags by the channel rules | Google's channel group, with Organic Video and Paid Video as Video, Organic Shopping as Referral, and Paid Shopping as Paid Search. Other groups go through the channel rules. |
source | Yes | Yes |
referrer | When the row has a referrer | When the source contains a dot |
utm_source, utm_medium, utm_campaign, utm_content, utm_term | When set | utm_source is the session source, utm_medium the medium, utm_campaign the campaign, utm_content the ad content, and utm_term the ad keyword |
page | With time on page and scroll depth | With time on page, no scroll depth |
entry_page | Yes | Yes |
exit_page | Yes | No |
country, region | Yes | Yes |
city | No | Yes |
browser | Yes | Yes |
browser_version | Yes | No |
os, os_version | Yes | Yes |
device | Yes | Yes |
event | Yes | Yes, without Google's own page_view, session_start, first_visit, user_engagement, and scroll |
Google reports name metrics differently. misomoon reads them this way:
| misomoon | From Google |
|---|---|
| Visitors | Total users |
| Visits | Sessions |
| Pageviews | Views |
| Bounces | Sessions minus engaged sessions |
| Visit duration | User engagement duration |
| Time on page | User engagement duration of the page, divided by its sessions |
| Events | Event count |
What misomoon drops
These events never reach a report:
| What | Rule | Where |
|---|---|---|
| Your own visits | A misomoon_ignore key in the browser's local storage stops m.js from sending anything. Exclude yourself shows how to set it. | m.js |
| Automated browsers | m.js sends nothing when navigator.webdriver is true. | m.js |
| The overlay tab | A page opened with #misomoon-overlay sends nothing. | m.js |
| Verified bots | Cloudflare marks the request as a verified bot. | Worker |
| Low bot scores | Cloudflare's bot score is below 10, when the request has one. | Worker |
| Bot user agents | The user agent is missing, shorter than 20 characters, or matches BOT_UA in packages/core/src/ua.ts. The pattern covers, among others, search and AI crawlers, link previews, headless and automated browsers, page speed tools, uptime monitors, and HTTP libraries. | Worker |
| Bad beacons | The body is over 16 KB or isn't JSON. The site id or the URL is missing. The URL isn't http or https. The event name is empty, over 120 characters, or holds a control character, ;, or ` | `. |
| Foreign pages | The site doesn't exist, or the page's host isn't the site's domain or a subdomain of it. | Worker |
| Excluded paths | A pageview or engagement ping on a page that the site's path rules leave out. Custom events on that page still count. Choose what to track explains the rules. | Worker |
| Events past the daily cap | Events after the site's cap for the UTC day. Daily ingest cap explains the cap. | Worker and queue consumer |
| Late engagement pings | An engagement ping that comes more than 30 minutes after its visit's last activity. | Queue consumer |
| Repeats | An event whose id is already stored. | Queue consumer |
An event whose client timestamp is more than 5 minutes from the server's clock keeps the event and takes the server's time instead. Why are my numbers lower than in Google Analytics? lists other reasons why counts differ between tools.