Skip to content

setFrequencyCaps

Configure frequency caps for placements or creative labels. Calling this method replaces the current cap configuration.

window.htag.api('1').setFrequencyCaps([
{
id: 'interstitial',
elementIds: ['interstitial-slot'],
limits: {
minIntervalSeconds: 300,
maxImpressions: 3,
windowSeconds: 86400,
},
},
{
id: 'summer-campaign',
frequencyCapLabels: ['summer-2026'],
limits: { maxImpressions: 1, windowSeconds: 3600 },
},
]);

Placement caps stop the placement before its Prebid and Google auctions. Label-targeted frequency caps let the auction run and exclude capped bids from winner selection. A creative supplies its label through the bid config extension:

<!-- @@extend_bid_config:{"frequencyCapLabel":"summer-2026"}@@ -->
  • caps (required): Array of frequency-cap objects.
    • id: Unique non-empty counter ID.
    • limits: At least one of minIntervalSeconds or maxImpressions. windowSeconds makes maxImpressions a rolling-window limit; without it, the maximum applies to the stored lifetime. A windowSeconds without maxImpressions limits nothing and is rejected.
    • Exactly one target: non-empty elementIds, or non-empty frequencyCapLabels matching [A-Za-z0-9_.:-]{1,64}.

Impression history is stored in localStorage, so it survives page loads. A “once per visit” cap is expressed as a time window, for example { maxImpressions: 1, windowSeconds: 3600 }.

Invalid caps are logged and ignored. If storage is unavailable, htag fails open: caps stop blocking rather than blocking everything.

Impressions are recorded when an ad actually renders, and nothing holds the remaining limit between the moment a target is selected and the moment it renders. A cap shared by several targets can therefore be exceeded.

Placement caps are exact within one auction batch: the pre-auction gate counts the admissions it has already granted, so two placements of the same batch never both take the last impression of a cap. That protection does not span batches — lazy-loaded placements are auctioned in separate batches, and a batch does not wait for the previous one to render. Label-targeted frequency caps are applied per bid during winner selection and are not protected even within a batch.

The overshoot is bounded only by the number of decisions already in flight when the recorded history reaches the limit. The code sets no numeric bound, and raising the limit does not make the count exact either: with a limit of 10, a history of 9 and three targets selected together, all three still render.

If the exact count matters, put the cap on a single target.

Tabs do not coordinate. Each tab keeps its own view of the history while it renders, and the stored history is updated as a separate read and write rather than a transaction, so parallel tabs can both exceed a cap and overwrite each other’s impressions.

Auto-reload is render-driven: the next timer is armed only after a successful render. A placement suppressed by a cap renders nothing, so the reload chain ends there — exactly as it does after any other no-fill. The placement is requested again on the next page transition or refreshAds, not at the moment the cap expires.

Suppression also leaves the slot untouched: htag never blanks a placement that receives no ad, so an ad rendered before the cap was reached stays visible until the page navigates. Clear it from the page if that matters.

Returns the Htag API object, allowing for method chaining.