All sections

Platform Target Count Constraints

Every execution platform imposes its own radius floors, target-count ceilings, and unsupported-geometry limits, and an H3 result set must be fitted to them, not assumed compatible.

conservativestableh35 min read
Source geometry
h3_cell_set
Destination geometry
platform_geo_id, point_radius

Purpose

A canonical H3 cell set is an interchange format; no advertising platform executes on H3 cells directly. Every platform imposes its own constraints on what a targetable unit can look like, and a conversion that ignores them produces a target list the platform will reject, silently truncate, or silently re-interpret. This page enumerates the recurring constraint classes and the mitigation for each, generically — see data/platforms.yaml for named platform-class instances of these limits.

Source geometry and destination geometry

Source geometry is an h3_cell_set at whatever resolution the canonical representation was built at. Destination geometry is whatever the target platform accepts: platform_geo_id (native regions), point_radius (circles), or occasionally a simplified polygon — never H3 cells themselves, since no mainstream ad platform has native H3 support.

Exactness class

Conservative by design: the fitting process in this page trades resolution and target-count for platform executability, and every mitigation below either coarsens the footprint or drops a request outright rather than silently exceeding a hard platform limit.

The constraint classes

Minimum radius
A platform floor (commonly 1 km) below which a point-radius target cannot be executed. A fine H3 cell's inscribed or circumscribed radius can fall below this floor, making the cell un-executable as a circle.
Maximum radius
A ceiling (commonly tens of km) above which a single circle cannot be drawn, forcing large contiguous areas to split into multiple circles.
Radius increments
Platforms round a requested radius to a fixed increment (e.g. nearest 100 m), changing executed coverage from the requested value.
Target-count limits
A hard cap on distinct targeting entries per line item (hundreds to tens of thousands), which a fine H3 polyfill of a large area can exceed by orders of magnitude.
Unsupported polygons
Some platforms accept only circles and native IDs, forcing every polygon-derived target to be approximated by circles regardless of shape fidelity loss.
Unsupported exclusions
A platform without exclusion support cannot express include-A-minus-B; the exclusion is rejected or silently dropped, executing on the full inclusion set.
Platform-native IDs only
Some platforms accept only their own named geography IDs, requiring a maintained crosswalk from H3 with an accepted precision loss.
Coordinate rounding
Platforms may round submitted circle-center coordinates on ingest, shifting the executed center by up to the rounding's implied distance.
Undocumented deduplication
Some platforms silently merge or drop entries that overlap beyond an undocumented threshold, changing the executed count without warning.
Optimized targeting expansion
Some platforms auto-widen a small-audience target to hit a delivery goal, expanding the footprint beyond the submitted geometry unless opted out.
Reporting at a coarser level
Delivery and outcome reporting is often returned only at a coarser native geography (DMA, region), making the executed-vs-reported gap unmeasurable from reporting alone.
Asynchronous boundary updates
A platform's native geography IDs can be redefined on the platform's own schedule, unsynchronized with the boundary vintage used to build the crosswalk.

Containment rule and boundary behavior

Fitting an H3 cell set to a platform's constraints is, by construction, conservative-toward-executability, not conservative-toward-coverage: the process may coarsen resolution (increasing overreach) or drop unexecutable elements (reducing coverage) to satisfy a hard limit. Both outcomes must be reported — the fitted target list is not the same geography as the canonical H3 input, and the gap has a direction (coarsening overreaches; dropping underreaches) attributable to the constraint that forced it.

Resolution behavior

Resolution is the primary lever for fitting target-count limits: compacting adjacent same-value cells (compact) and, where insufficient, coarsening to a higher parent resolution reduces cell count at the cost of boundary precision. For minimum-radius floors, coarsening is again the lever — a coarser cell's circumscribed radius is larger and more likely to clear the floor — while for maximum-radius ceilings the opposite applies: a circumscribed circle exceeding the ceiling must split into smaller circles.

Units and CRS

EPSG:4326 for all geometry; radii in meters unless a platform's API documents feet or another unit, in which case the conversion must convert explicitly and record the platform's native unit in the ConversionRecord.

Algorithm

import { compact, uncompact } from "@/lib/h3/hierarchy";
import { circumscribedCircle } from "@/lib/h3/circles";

function fitToPlatform(cells: string[], platform: {
  minRadius: number | null;
  maxRadius: number | null;
  maxTargets: number | null;
}) {
  let working = compact(cells);

  // Coarsen resolution stepwise until under maxTargets.
  while (platform.maxTargets && working.length > platform.maxTargets) {
    working = compact(coarsenOneLevel(working));
  }

  // Fit each remaining cell's circumscribed circle to min/max radius.
  const circles = working.map((cell) => {
    const { radiusMeters, center } = circumscribedCircle(cell);
    const clamped = clampRadius(radiusMeters, platform.minRadius, platform.maxRadius);
    return { center, radiusMeters: clamped };
  });

  return circles;
}

Parameters

The target platform's declared minRadius, maxRadius, radiusIncrements, maxTargets, polygonSupport, exclusionSupport, adminIdSupport, and nativeCellSupport — all sourced from a platform capability record such as data/platforms.yaml, never assumed or hardcoded per campaign.

Outputs

A platform-executable target list (circles, native IDs, or a simplified polygon set) alongside a record of every coarsening step, dropped exclusion, and cell merged past its original boundary — the inputs needed to compute overreach_ratio and coverage_ratio against the canonical set.

Quality metrics

overreach_ratio and coverage_ratio against the pre-fitting canonical cell set, per the platform_limit_optimized profile (conversion-profiles), whose stated guarantee is that the result respects maxTargets and minRadius for the named platform and whose stated tradeoff is that coarsening enlarges the effective footprint.

Edge cases

minimum-radius and radius-increments interact: a cell coarsened just enough to clear the minimum floor can still shift meaningfully once the platform rounds to its nearest increment, so the final check must run against the platform-quantized radius, not the pre-rounding one. platform-native-ids-only and unsupported-exclusions both require a fallback decided in advance — pre-subtracting an exclusion in cell space before crosswalking to native IDs is the standard mitigation, flagged as reported-vs-executed divergence regardless.

Assumptions and limitations

This page documents constraint classes generically; exact numeric limits must be sourced from the platform's current API documentation via a capability record, never from memory or this page — platform limits change without notice, and a stale assumption here is a stale-boundaries-class failure applied to platform capabilities rather than geographic ones.

Illustration — the minimum-radius floor

An R9 inscribed circle (172 m, green) sits below a 400 m platform minimum (amber dashed): the cell cannot be executed as a circle at this resolution without coarsening.
Rendered from the tested conversion code · An R9 inscribed circle (172 m, green) sits below a 400 m platform minimum (amber dashed): the cell cannot be executed as a circle at this resolution without coarsening.
Edge cases affecting this page
  • - A platform floor (e.g. 1 km) makes sub-floor cells un-executable as circles.
  • - Platforms round radii to increments, changing coverage/overlap.
  • - No polygons/coordinates — everything must be crosswalked to platform IDs, losing sub-unit precision.
  • - 'Include A minus B' cannot be expressed on platforms without exclusion support; the exclusion is silently dropped.