How Epom computes your numbers: General, Advanced and raw-log reports
What each report type is answered from — stored daily and hourly totals for General, Header Bidding and Targeting Cookie, request-level logs for Advanced and the event logs — why the figures can disagree, and which report to trust for billing versus exploration.
Two Epom reports over the same dates can show different numbers, and both can be correct. That is expected — it is the direct consequence of Epom answering different report types from different data, with different freshness, different dimensions and, in places, different counters. This page explains what each type reads and why, so you can tell which report to trust for what.
If you just need the “why don’t my numbers match” checklist, go to Analytics discrepancies. This page is the mental model behind that checklist.
Which data answers which report
When you run a report, the Type of reports selector on the Filter tab decides which data answers it:
| Type | Reads from | Row = | How it runs |
|---|---|---|---|
| General | Daily and hourly aggregates the ad servers produce | One aggregated row per your group-by | Inline, no progress bar |
| Header Bidding | Its own daily and hourly aggregates | One row per fill source (direct campaign, publisher ad server, AdX / AdSense, a bidder, unfilled) | Inline |
| Targeting Cookie | Its own daily cookie-targeting aggregates | Cookie name/value statistics | Inline |
| Advanced | The full ad-request log | Aggregates with many extra dimensions | Background job with a progress bar |
| Raw logs | The individual event logs | One row per event | Background job with a progress bar |
Only Advanced and the raw logs read the full event logs; the other three read pre-aggregated statistics. The per-type availability, permissions and controls are in Report types; the rest of this page is about General, Advanced and the raw logs, because those are the ones that get compared.
General — the aggregated statistics
General reads hourly and daily aggregates of what the ad servers recorded. There is no background computation and no progress bar: you ask, it queries, it answers. It is the type that feeds dashboard widgets and scheduled e-mails, together with Advanced, and it is the type that carries the advertiser Status (finalization) grouping.
Advanced — recomputed from the ad-request logs
Advanced recomputes aggregates from the full ad-request log, which is why it can break your data down by dimensions General doesn’t carry (browser, OS, device model, carrier, risk, custom parameters, and more — see Analytics dimensions). It runs as a background job, and its results are cached per query window: a repeat of the same query is answered from the cache until a newer hour of data has loaded (or for good, once the window ended two or more days ago).
Raw logs — one row per event
The Impressions / Clicks / Conversions Log types read the individual event records — the actual per-impression, per-click, per-conversion rows — with the same cache rule as Advanced. Use them for auditing a specific event, comparing an event stream against a partner, or inspecting invalid traffic. They have no group-by — they are event lists, not aggregates.
Freshness: nothing shows the current hour
No report type is live. Ad servers collect events in hourly batches, and a batch becomes reportable only once its hour has ended, so the hour in progress is never in any report. The aggregated types (General, Header Bidding, Targeting Cookie) and the log-based types (Advanced and the raw logs) load on separate schedules — by default about a minute past the hour and roughly 25–30 minutes past the hour respectively. The exact schedule is a per-network setting that Epom support or your account manager can change. Report types has the table.
Why they disagree — the real reasons
1. The newest hours differ by report family
Both families lag by at least the hour in progress, and because the two loads run on their own schedules, General and Advanced can include a different last hour. For today, any difference between them may be nothing more than “one family has loaded an hour the other has not”. “Today” is always provisional in every type — for final daily numbers, report on yesterday or earlier.
2. Yesterday can still move
A day is assembled from hourly batches as they are loaded, so a batch that arrives late revises the day after the fact. Advanced and the raw logs add their cache on top: two runs of the same query minutes apart return the cached result and look identical, and a run after the next hour loads can differ.
3. The two report families count differently
General and Advanced are not two views of the same numbers; each computes its ratios from its own counters:
- eCPM and the other money-per-thousand figures. On General, eCPM divides money by impressions. On Advanced it divides by eligible impressions — deliveries minus matched passbacks minus rejected impressions — so the same money over the same traffic gives a higher eCPM there when some impressions were rejected. See CPM, eCPM and RPM and invalid traffic.
- Conversions. System conversions — the VAST quartile, viewability and player-interaction events — are left out of the Conversions column on General (from the release-152 upgrade day on; earlier days keep their old totals) and on Advanced (which recomputes from the raw logs, so it drops them for every day since release 149). On a network whose Advanced report runs on compacted logs the count comes from a pre-aggregated figure that still includes them, so the same network can show more conversions there. Their money still lands in Gross and Net; group by Action to see the system events themselves.
4. A compacted Advanced setup drops some group-by dimensions
Advanced reads either the full logs (the default) or, on some networks, compacted logs that don’t carry every field. On compacted logs a set of Advanced dimensions becomes filter-only — you can filter by them but not group by them. The list removed from group-by includes:
Mobile Carrier, Connection Type, Language, Accept-Language, Time Zone Name, Browser Country, Traffic Source, Incognito Mode, Is Web App, Platform, Placement Size, Placement Type, Device Format, Proxy, Device Release Year, Device Vendor / Model / Model Code, Risk Level and Risk Category — plus, on some networks, a few further fields.
The practical trap: filtering an Advanced report on one of these can legally return zero rows even though the totals report shows traffic — because the field the filter needs may be absent from the compacted logs. If a filtered Advanced report comes back empty, drop the exotic dimension and re-run before concluding “data loss”. Full per-dimension detail is in Analytics dimensions; ask Epom support or your account manager whether your network runs on compacted logs.
Two more sources of “different numbers” that aren’t the report type
These get blamed on the report type but are independent:
- Time zone. Only the Advanced report has its own Time zone selector (default UTC); every other type (and dashboards) has no zone control: days are cut where the ad servers cut their hourly logs, the network’s reporting time zone. Two reports comparing different zones shift events across the midnight boundary. This is a bucketing difference, not a data difference — see Which time zone do reports use?.
- Permissions and sharing. Column families, individual columns, group-by and filter options are each permission-gated, and reports only include entities you can view. A colleague seeing different numbers or columns is usually a role difference, not a report difference. The shipped Publisher and Advertiser roles, for instance, read the Publisher or Advertiser column family rather than Base. See metrics and dimensions.
Which time zone do reports use?
| Where | Time zone | Can you change it? |
|---|---|---|
| General report, dashboards, widgets | The network’s reporting time zone — one zone for the whole network | No. There is no per-user or per-account setting; General rows are kept per day and hour in that zone |
| Advanced report | The Time zone you pick on the Filter tab, UTC when you pick nothing | Yes, per report |
| Scheduled report e-mails | Sent at the hour you choose, in UTC | The data inside follows the report’s own type |
To find your network’s reporting time zone, call GET /rest-api/network/settings.do — the
answer carries reportingTimeZone with its id and current utcOffset. Dashboards show day
labels exactly as stored, without shifting them into your browser’s zone.
The Advanced selector offers fixed UTC offsets (UTC−12 … UTC+14), not named regions: there is
no daylight-saving switch, so a report that should follow New York time uses UTC−5 in winter and
UTC−4 in summer. Over the API the same choice is the usersTimeZoneId parameter with the enum
name — UTC_0, UTC_PLUS_2, UTC_MINUS_5 — and an unknown value silently falls back to UTC.
If you need daily totals in your own time zone and your network’s zone is a different one, run the numbers as an Advanced report with your zone selected, over settled days. A General report cannot be re-bucketed.
How far back each report goes (data retention)
- General is the long-term store; its hourly breakdown covers only the most recent two weeks by default, so an hour-by-hour General report for an older period comes back empty.
- Advanced and the raw logs read the event logs, which are kept only for a short window — a few days, set per network (two days by default). An Advanced report for “last 30 days” returns only the days still in that window; use General for longer periods and for invoicing. Some event types (for example clicks or conversions) can be kept longer than the rest, so the Clicks Log may reach further back than the Advanced report.
- To keep event-level data longer, use the raw event export to your own storage.
Which report to trust for what
| You want to… | Use | Because |
|---|---|---|
| Bill, reconcile, close a period | General, over yesterday or earlier | It carries the finalization Status grouping |
| Explore by browser / OS / device / risk / custom params | Advanced | Only it carries those dimensions |
| Audit an individual impression / click / conversion | Raw logs | One row per event, with per-event attributes and validity flags |
| Power a dashboard widget or scheduled e-mail | General or Advanced | Those are the two types widgets and scheduled e-mails run; the raw logs, Header Bidding and Targeting Cookie cannot back one |
| Match a partner’s daily totals precisely | Advanced with the partner’s time zone, over settled days | Only Advanced lets you align the day boundary |
| See which source filled a header-bidding slot | Header Bidding | It is the only type with the fill-source split |
Note: for anything financial, prefer General over yesterday-or-earlier. It is the report that reflects accounting-period status — Advanced and raw logs are for analysis, not billing. It is not “fresher” than the others: every type waits for the hour to end.
General vs Advanced vs raw logs: which report counts requests, impressions and no ads
The same word means a slightly different count in each report. Read this table before comparing a General number with an Advanced one:
| Question | General | Advanced | Raw logs (Impressions / Clicks / Conversions Log) |
|---|---|---|---|
| What is Requests? | Impressions + No-ad answers for the placement — General has no separate request counter | Direct requests: every original ad request the ad server received (repeats are a separate Repeated requests column) | No request rows at all — the logs list impressions, clicks and conversions |
| What is an Impression? | Counted impressions (invalid ones excluded) | Impressions = eligible impressions: deliveries minus rejected (invalid) impressions and matched passbacks | One row per impression event, with a validity filter where the network stores invalid events |
| Where are no-ad answers? | Inside Requests (and so inside Fill Rate) | No ads, Returned requests, Wasted requests — see Advanced report metrics | Not listed |
| Fill Rate | impressions ÷ (impressions + no-ad answers) | eligible impressions ÷ direct requests | — |
| Money from a fixed daily / monthly price | Spread over the period’s impressions (see below) | Not included | Not included |
| City, browser, OS, referer, custom parameters | No | Yes | Per event (IP, user agent, location, referer, custom parameters) |
| How far back | Months and years (hour rows ≈ two weeks) | A few days | A few days |
| Time zone | Network reporting time zone | Your pick on the Filter tab, UTC by default | No selector |
So General Requests is usually lower than Advanced Direct requests: a request whose ad was returned but never rendered — the visitor left, an ad blocker removed it, a third-party tag inside the ad failed — produces neither an impression nor a no-ad answer, so General never counts it, while Advanced counted the request the moment it arrived. Advanced is the report to use when the question is “how many requests did the placement get”; General is the one for “how many impressions do we bill”.
Corner case: General’s Requests and Fill Rate exist only on the supply side. Group or filter by an advertiser, campaign, banner or conversion action and both columns disappear — a request happens before a banner is chosen, so it belongs to no advertiser.
Fixed daily or monthly price: why Net is spread and missing from the logs
A site or placement priced Cost per day or Cost per month pays a flat fee, not a price per impression. The ad server cannot put that fee on any single impression, so:
- General spreads the fee over the period’s impressions: every day row of the placement gets
fee × its impressions ÷ all impressions of the day (or month)as Net, so the period’s Net adds up to the fee. The spreading runs several times a day for today and this month, re-runs for yesterday after midnight, and settles last month on the 1st — so the per-day Net of the current month keeps shifting until the month is over. - Hour rows are not spread — an Hour breakdown of such a placement shows no fee.
- Advanced and the raw logs carry no share of the fee at all: an exported Impressions Log shows those impressions with no Net. This is expected, not lost revenue — invoice from General.
Raw event files in your own storage (S3, Google Cloud Storage, SFTP)
Besides the Impressions / Clicks / Conversions Log reports, Epom can switch on a
raw event export for your network: every hourly event file the ad servers write is also uploaded, as gzipped
Parquet, to a bucket you own — Amazon S3, Google Cloud Storage or an SFTP server. Files land under
stream=<stream name>/t=<event type>/dt=<YYYY-MM-DD>/h=<hour>/, one file per ad server per hour.
The export is set up by Epom support (bucket, credentials, which stream); there is no self-serve
page for it, so send the storage details to support. It includes the same per-event fields as the log reports — IP, user agent, location,
referer, custom parameters, entity ids, money — and is the way to keep event-level data longer
than the few days the log reports keep.
Corner case: an upload to your bucket that fails is retried by the ad server itself, once an hour, from the copy on the analytics cluster — so a missing hour normally appears within the next hour. That copy is kept only for the cluster’s retention window (often three days); a gap older than that cannot be re-sent. To re-send an hour on demand while it is still inside that window, ask Epom support or your account manager.