Capping matrix
The complete capping enum — 18 types, 5 subjects, 7 period types — which of them a user can actually reach, and the permission that gates each one.
The value lists behind frequency capping, in full, plus which of their values a user can actually reach. For the walkthrough — how a cap counts, when its window rolls over, what Flat does — see Set up frequency capping.
The enum has 18 values; the product offers 12 of them
The capping type list has 18 values. A value is one kind of cap fixed to one entity level, so the same kind appears up to four times. Of the 18, 12 are reachable in the product and 6 are not — the three Request values, whose permissions are granted to no role, and the three DSP values, which every write path refuses. That is the 1 + 4 + 4 + 3 the combo feeds return.
| Value | Kind | Level | Prefix | Reachable? |
|---|---|---|---|---|
ADVERTISER_FREQUENCY | Frequency | Advertiser | af | ✔ |
CAMPAIGN_FREQUENCY | Frequency | Campaign | c | ✔ |
CAMPAIGN_CLICKS | Click | Campaign | cc | ✔ |
CAMPAIGN_ACTIONS | Action | Campaign | ca | ✔ |
CAMPAIGN_NO_CLICK | No-Click | Campaign | cnc | ✔ |
CAMPAIGN_REQUEST | Request | Campaign | cr | — no role can hold the permission |
BANNER_FREQUENCY | Frequency | Banner | b | ✔ |
BANNER_CLICKS | Click | Banner | bc | ✔ |
BANNER_ACTIONS | Action | Banner | ba | ✔ |
BANNER_NO_CLICK | No-Click | Banner | bnc | ✔ |
BANNER_REQUEST | Request | Banner | br | — no role can hold the permission |
PLACEMENT_FREQUENCY | Frequency | Placement | pfc | ✔ |
PLACEMENT_CLICKS | Click | Placement | pcc | ✔ |
PLACEMENT_ACTIONS | Action | Placement | pac | ✔ |
PLACEMENT_REQUEST | Request | Placement | pr | — no role can hold the permission |
CAMPAIGN_DSP_FREQUENCY | DSP frequency, 1 day | Campaign | cd | — refused on every path |
CAMPAIGN_DSP_FREQUENCY_MONTH | DSP frequency, 1 month | Campaign | cdm | — refused on every path |
CAMPAIGN_DSP_RECENCY | DSP recency | Campaign | cdr | — refused on every path |
The prefix is not decoration: it is the name of the browser cookie the counter lives in, and
the first half of the composite row id ({id}:{TYPE}) the delete call takes.
What each level serves into the Capping type list
This is what the four combo endpoints actually return, after permission filtering, on a network whose roles have never been hand-edited.
| Kind | Advertiser | Campaign | Banner | Placement |
|---|---|---|---|---|
| Frequency | ✔ | ✔ | ✔ | ✔ |
| Action | — | ✔ | ✔ | ✔ |
| Click | — | ✔ | ✔ | ✔ |
| No-Click | — | ✔ | ✔ | — (no such value exists) |
| Request | — | (exists, never granted) | (exists, never granted) | (exists, never granted) |
So the lists come out at 1 type for an advertiser, 4 for a campaign, 4 for a banner, 3 for a placement — and in that order: Frequency, Action, Click, No-Click. The advertiser level is deliberately minimal: one impression cap that everything beneath it shares.
Corner case — Request capping is unreachable, not merely ungranted. Its two permissions (Request Capping and Inventory Request Capping) exist as permission definitions, but the migration that created them inserted only the two identities. It never created the role entries or the grants that a permission needs to be holdable, and neither the seed nor any later script grants them, so no role holds either one. Until Epom inserts those rows by hand, no role can see Request capping in any list.
Corner case — the three DSP types are refused everywhere. The campaign list drops them unconditionally, with no permission that restores them, and the shared validator answers Access denied for add, update and delete alike, through the REST API too. Ad serving ignores them. If a row of one of these types is already on a campaign, it can be listed and cannot be removed through any supported call.
Which permission gates which type
Each kind of cap has its own permission on the role: Frequency Capping, Click Capping, Action Capping and Request Capping. No-Click has none of its own and follows Frequency Capping. The DSP types are never listed and always refused.
Placement caps are the exception: the Capping type list asks for the demand-side permission, but saving asks for its Inventory twin (Inventory Frequency Capping and so on). A publisher role with only the inventory permissions therefore gets an empty list, and a role with only the demand permissions gets a list it cannot save from. Ask for both when placement capping is needed.
The card itself also needs Manage Capping & Limitations (demand) or Manage Inventory Capping (supply), enabled or read-only.
Two names for the same row
A cap is labelled one way in the Add dialog and another in the grid’s Type column.
| Capping type list | Grid Type column |
|---|---|
| Frequency Capping | By impressions |
| Action Capping | By conversions |
| Click Capping | By clicks |
| Request Capping | By requests |
| No-Click Capping | No-Click Capping — the one kind with no short label |
Note: No-Click Capping stays in English in every interface language, in both the dialog and the grid.
Subjects
Five values, from GET /capping-subject-types.do — note the root path, not /account. The
subject is set per cap row, not once for the entity, and it is fixed in the order
below.
| Subject | Id | Label | Counter lives in | Available when |
|---|---|---|---|---|
USER_COOKIE | 1 | User (cookie-based) | a cookie on the ad-serving domain | nothing — this is the default for a new row |
USER_SERVER_SIDE | 4 | User (server-side storage) | the network’s server-side capping store, keyed by the resolved visitor id | server-side capping storage enabled |
USER_MIXED | 5 | User (cookie-based + server-side storage) | the cookie where a cookie is possible, the store where it is not | server-side capping storage enabled |
IP | 2 | IP | the store, keyed by the client IP | server-side storage and IP capping are enabled for the network, and your role allows IP capping |
LES_IP | 3 | L.E.S. IP | the store, keyed by the last external source IP — the address seen before proxies | server-side storage and L.E.S. IP capping are enabled, and your role allows L.E.S. IP capping |
The server-side counter is keyed by the visitor id the ad server resolves for the request. In the
default (mixed) identity mode that is, in this order: an explicit user id parameter, the Epom UUID cookie, the device advertising ID (ifa) —
which is what separates the viewers behind an SSAI stitcher on apps and connected TV — and last a
fingerprint of IP, user-agent and language. A placeholder or all-zero advertising ID counts as no
ID.
The endpoint filters only on the two permissions; the network switches are checked by the card. The Subject column and its selector appear only when server-side storage is on and at least one of the two IP subjects is both granted to you and enabled on the network. When the column is hidden, existing rows keep and still enforce whatever subject they were saved with.
When a cookie counter cannot be used
A request is treated as unable to keep a capping cookie when any of these holds:
- the ad tag reported private browsing (
im=1); - the browser is Safari, Mobile Safari, Firefox, Firefox Mobile, Firefox Minimo, Brave or DuckDuckGo;
- the operating system is iOS, iPadOS or Apple TV;
- neither the browser nor the OS could be identified at all.
For a USER_MIXED row that flips the counter to server-side storage for that request. For a
plain USER_COOKIE row there is no fallback, so the cap simply under-counts that traffic.
The tag’s cookie-policy value overrides all of this: 1 turns off cookies and server-side
capping, 2 turns off cookies but keeps server-side capping, 3 drops only the user-ID cookie.
A network’s GDPR no-consent restriction maps onto the same values. See
Frequency cap not working.
Corner case — No-Click capping is cookie-only. The two No-Click values have no server-side counterpart at all: the mapper that writes counters to the store has no entry for them and skips them silently. A No-Click row with subject User (server-side storage) is never counted and never fires, and a mixed one stops working for exactly the visitors who cannot keep cookies. Leave No-Click on the plain cookie subject.
Period types
Seven values, from GET /time-period-types.do, in this order.
| Period type | Id | Label |
|---|---|---|
SECOND | 6 | Second(s) |
MINUTE | 0 | Minute(s) |
HOUR | 1 | Hour(s) |
DAY | 2 | Day(s) |
WEEK | 3 | Week(s) |
MONTH | 4 | Month(s) |
YEAR | 5 | Year(s) |
The window is Period × Period type, measured from the first counted event for that visitor
and that cap. Month and year are calendar lengths, not fixed 30- and 365-day blocks: the ad
server computes the window length by adding the period to a calendar date. It does that once,
when the cap is loaded into the serving cache, so a one-month window loaded during February is
28 days long for as long as that cache entry lives.
Field ranges and defaults
| Field | Add-dialog default | Add-dialog input allows | Server enforces |
|---|---|---|---|
| Capping type | first type in the list | — | must match the entity’s level, or the save is refused as Capping type is incompatible with entity |
| Subject | Please select… — saved as User (cookie-based) | the permitted subjects | the Capping IP Subject permission for IP |
| Amount | 0 | 0 – 100 000 | 0 – 8 388 607 |
| Period | 1 | 0 – 100 000 | 1 – 255 |
| Period type | Day(s) | the seven above | the seven above |
| Flat | off | on / off | — |
The two ranges disagree on purpose in neither direction — the form is simply looser than the
validator. A period of 0 or of 300 is accepted by the input and refused on save. An
Amount of 0 does not restrict anything: the ad server skips any cap whose amount is 0.
The entity’s own default period type is HOUR; the Add dialog overrides it to Day(s) before
you see it, so an HOUR row can only arrive through the API.
The DSP rows, for reading existing data
These cannot be created (see the corner case above), but a campaign may already carry one. Their field locks are:
| Value | Pinned | Editable in the grid |
|---|---|---|
CAMPAIGN_DSP_FREQUENCY | Period = 1, Period type = Day, Flat off | Amount only |
CAMPAIGN_DSP_FREQUENCY_MONTH | Period = 1, Period type = Month, Flat off | nothing is locked — the grid has no rule for this value |
CAMPAIGN_DSP_RECENCY | Amount = 1, Flat off, Period type = Minute | Period only, 1 – 60 |
Any edit is refused by the server regardless, so the unlocked month variant is a cosmetic inconsistency rather than a way in.
REST API surface
| Level | Create | List | Per-kind set / update / remove |
|---|---|---|---|
| Advertiser | POST /rest-api/advertiser/capping/{advertiserId}.do | GET on the same path | — |
| Campaign | POST /rest-api/campaign/capping/{campaignId}.do | GET on the same path, plus GET /rest-api/campaign/capping/bulk.do | frequency, click, action, no-click |
| Banner | POST /rest-api/banner/capping/{bannerId}.do | GET on the same path | frequency, click, action, no-click |
| Placement | POST /rest-api/placement/capping/{placementId}.do | GET on the same path | — |
Any cap row, at any level, can also be changed or removed by its composite id ({id}:{TYPE})
through POST /rest-api/capping/{cappingId}.do and POST /rest-api/capping/delete.do.
Corner case: the spec lists all 18 values in the
typeenum of all four create endpoints, including the ones that belong to a different level. The description narrows it correctly, and the server rejects a mismatch cleanly — so do not read that list as the values a given endpoint accepts.