Events
The Events system allows you to respond to various lifecycle events that occur during ad loading and display. By registering event listeners, you can execute custom code at specific points in the ad lifecycle.
Supported Events
Section titled “Supported Events”Fired once when htag is fully initialized and ready to process ad requests.
Event data: None
element.exists
Section titled “element.exists”Fired when a placement’s DOM element is found on the page. Can be fired multiple times — once per (re)appearance of the element within a load cycle, e.g. when a client-side re-render or dynamic placement swaps the container. Listeners must be idempotent.
Event data:
{ elementId: string, // The placement identifier element: HTMLElement, // The DOM element that was found accountForHydration: boolean, // Whether hydration was awaited before treating the element as ready appearanceCount: number // How many times the element (re)appeared this load cycle (1-based); > 1 means the container was swapped mid-cycle}element.requestable
Section titled “element.requestable”Fired when lazy loading determines the element should request ad data or immediately for non-lazy-loaded placements.
Event data:
{ elementId: string, // The placement identifier element: HTMLElement, // The DOM element}element.renderable
Section titled “element.renderable”Fired when lazy loading determines the element should render.
Event data:
{ elementId: string, // The placement identifier element: HTMLElement, // The DOM element}element.beforeRender
Section titled “element.beforeRender”Fired before a placement begins rendering, after auction winners have been determined. This event indicates which rendering path will be used (direct or Google Ad Manager).
Timing:
- Direct rendering path (
renderPath: 'direct'): Fires immediately before the Prebid.js direct render is initiated - Google rendering path (
renderPath: 'google'): Fires when theSlotResponseReceivedevent is received from Google Publisher Tag, indicating that the ad response has been received from the server and rendering is about to begin
Note: This event does not fire for blocked placements (e.g., companion placements in a roadblock scenario that don’t render).
Event data:
{ elementId: string, // The placement identifier renderPath: 'direct' | 'google' // Rendering method: 'direct' for Prebid.js direct render, 'google' for Google Ad Manager mediation}Render path values:
'direct'- Ad will be rendered directly via Prebid.js without Google mediation'google'- Ad will be rendered through Google Ad Manager (includes both mediation and Amazon APS bids)
element.resolve
Section titled “element.resolve”Fired at most once per placement per render cycle when ad serving reaches an outcome, whether an ad is rendered or no ad can be served. Refreshing a placement starts a new render cycle.
The public event identifies the placement by elementId, without an auction ID. If a refresh starts while an earlier render is still in progress, a late resolve from that earlier render can arrive after the refresh and suppress the later public resolve. Do not use element.resolve to correlate overlapping auctions.
A placement that remains in the DOM also resolves when GAM finishes without an ad to display. This includes a mediation creative returned without a Prebid bid: GAM can report isEmpty: false because it served the mediation creative, even though there is no ad to display. The no-ad resolve can arrive before the mediation creative finishes clearing the placement; it does not signal that DOM cleanup has completed.
A mediation creative with a Prebid bid waits for that bid’s render outcome instead. If the creative never invokes the Prebid renderer and no render outcome is reported, the public element.resolve may never fire.
The event is not guaranteed for every configured placement: its element may never appear on the page, or a lazy placement may never reach its render gate. If GAM finishes after a placement’s element has been removed, htag still emits element.resolve without an adId. Earlier visibility proves only that the element existed at that moment; it can be removed or replaced before GAM finishes.
Event data:
{ elementId: string, // The placement identifier adId: string | undefined, // The ad ID if an ad was rendered, undefined if no ad was served bidder: string | undefined // The bidder code if an ad was rendered, undefined if no ad was served}auction.resolved
Section titled “auction.resolved”Fired once per auction after all winners have been determined, including roadblock bid evaluation. This event provides a complete map of all placements in the current preload group and their winning decisions.
Event data:
{ winners: WinnersMap; // Map of elementId to Winner objects (see structure below)}WinnersMap structure:
The winners object is a map where keys are element IDs (strings) and values are Winner objects:
{ 'placement-id-1': { type: 'direct', reason: 'cpm_threshold', bid: { /* Prebid BidAdapterBid object */ }, bidConfig: { /* Original bid configuration */ } }, 'placement-id-2': { type: 'mediation', reason: '', bid: { /* Prebid BidAdapterBid object */ } }, 'placement-id-3': { type: 'blocked', reason: 'roadblock', parentBid: { /* Parent bid that blocked this placement */ } } // ... more placements}Winner object structure:
{ type: 'direct' | 'mediation' | 'amazon' | 'blocked', // Rendering type reason: 'cpm_threshold' | 'google_disabled' | 'override' | 'priority' | 'roadblock' | 'amazon' | '', // Why this rendering path was chosen bid?: BidAdapterBid, // Prebid bid object (if applicable) parentBid?: BidAdapterBid | HtagAmazonBid, // Parent bid for roadblock companions bidConfig?: BidConfig, // Original bid configuration renderGroupElementIds?: string[] // Companion element IDs for roadblock groups}Winner type values:
'direct'- Ad will be rendered directly via Prebid.js without Google mediation'mediation'- Ad will be rendered through Google Ad Manager with Prebid mediation'amazon'- Amazon APS bid will be rendered through Google Ad Manager'blocked'- Placement blocked by roadblock (won’t render)
Winner reason values:
'cpm_threshold'- Bid CPM exceeded maxGoogleCpm threshold, bypassing Google'google_disabled'- skipGoogle configuration enabled for this placement'override'- Bid manually marked as override (must win)'priority'- Priority creative ID matched (bypasses normal auction)'roadblock'- Roadblock bid won, blocking companion placements'amazon'- Amazon APS bid won''(empty string) - Standard mediation path, no special reason
BidAdapterBid object (key fields):
{ adId: string, // Unique ad identifier adUnitCode: string, // Placement element ID auctionId: string, // Auction identifier bidderCode: string, // Bidder name (e.g., 'appnexus', 'rubicon') cpm: number, // Bid price currency: string, // Currency code (e.g., 'USD', 'EUR') creativeId: string, // Creative identifier width: number, // Creative width height: number, // Creative height mediaTypes: object, // Media types configuration object (e.g., { banner: { sizes: [[300, 250]] } }) mediaType: string, // [Runtime] Winning media type (e.g., 'banner', 'video', 'native') timeToRespond: number, // Bid response time in milliseconds ad: string // Creative HTML content // ... additional Prebid.js fields}Working with Event Listeners
Section titled “Working with Event Listeners”You can register event listeners using the addEventListener method and remove them using the removeEventListener method.
Related Methods
Section titled “Related Methods”- addEventListener: Register event listeners
- removeEventListener: Remove event listeners