Skip to content

Hydration

When a page is rendered on the server (SSR) or generated statically, the placement <div> elements appear in the DOM before the publisher’s frontend framework (React, Vue, Svelte, Astro, …) has finished hydrating them. If Htag rendered an ad into such an element too early, the framework’s hydration step would tear the ad iframe back out, leading to flicker, lost impressions, or duplicated requests.

The hydration mechanism lets the publisher tell Htag “this placement is in the DOM, but it is not yet safe to render into”. While the placement is marked as not hydrated, Htag keeps the placement in a waiting state and resumes the lifecycle automatically when hydration completes.

A placement element opts into hydration tracking by setting the data-hydrated attribute:

ValueMeaning
data-hydrated="0"Element exists in the DOM but is not yet hydrated — Htag will skip it.
data-hydrated="1"Element is hydrated — Htag processes it normally.
data-hydrated="" (empty)Treated the same as hydrated — Htag processes the element.
Attribute absentHydration tracking is disabled for this element — Htag processes it normally.

When Htag is waiting for a placement to become ready, it queries the DOM and applies a sequence of checks to the element:

  1. The element exists (document.getElementById(elementId) returns a node).
  2. The element is a fully initialized placement (data-adnz-placement is not "0").
  3. If the element has data-hydrated="0", treat it as if it were not in the DOM yet and keep waiting.

Step 3 only applies in lifecycle stages where Htag is about to render into the element. The data-hydrated flag is intentionally ignored when Htag is only preparing to request ad data, so bidding can happen in parallel with framework hydration without delaying impressions.

Lifecycle stageHonors data-hydrated="0"?
Ad request (request)ignored
Ad render (render)honored
Non-lazy load (none)honored

Htag watches the placement element with a MutationObserver configured to listen for changes to the data-hydrated and data-adnz-placement attributes. As soon as the publisher updates the attribute (for example, in a hydration callback), Htag re-evaluates the element and continues the lifecycle without polling.

In environments where MutationObserver is unavailable, Htag falls back to lightweight interval polling (≈ 64 ms) with the same outcome.

The recommended publisher integration pattern is:

  1. Server-render or statically render the placement container with data-hydrated="0".
  2. Once your frontend framework finishes hydrating the component that owns the container, set data-hydrated="1" on the same element.
  • Placements: Lifecycle attributes set by Htag, including data-adnz-placement.
  • Lazy Loading: How Htag schedules requests and renders relative to the viewport.