@@ -65,6 +65,7 @@ interface RTDConfig {
6565 targetingFromCache : ( config ?: RTDConfig ) => TargetingData | null ;
6666 handleRtd : ( reqBidsConfigObj : ReqBidsConfigObj , optableExtraData ?: any , mergeFn ?: any ) => Promise < void | null > ;
6767 instance : string ;
68+ waitForTargeting : boolean ;
6869}
6970
7071interface RTDOptions {
@@ -78,6 +79,7 @@ interface RTDOptions {
7879 forceGlobalRouting ?: boolean ;
7980 mergeStrategy ?: MergeStrategy ;
8081 instance ?: string ;
82+ waitForTargeting ?: boolean ;
8183}
8284
8385// Merge strategies for EIDs
@@ -162,22 +164,74 @@ function targetingFromCache(config: RTDConfig = {} as RTDConfig): TargetingData
162164}
163165
164166// Get targeting data from cache, if available
165- function readTargetingData ( config : RTDConfig ) : TargetingData {
167+ async function readTargetingData ( config : RTDConfig ) : Promise < TargetingData > {
166168 const cachedData = targetingFromCache ( config ) ;
167- if ( ! cachedData ) {
168- config . log ( "info" , "No cached targeting data found" ) ;
169- return { } ;
169+
170+ // Get auction delay from pbjs config
171+ const delay = ( window as any ) ?. pbjs ?. getConfig ?.( ) ?. realTimeData ?. auctionDelay ;
172+
173+ // If waitForTargeting is disabled, cache is not empty, or no delay configured, return immediately
174+ if ( ! config . waitForTargeting || cachedData || ! delay ) {
175+ if ( ! cachedData ) {
176+ config . log ( "info" , "No cached targeting data found" ) ;
177+ return { } ;
178+ }
179+
180+ // Validate targeting data structure
181+ if (
182+ ! cachedData ?. ortb2 ?. user ?. eids ||
183+ ( ! Array . isArray ( cachedData ?. ortb2 ?. user ?. eids ) && Object . keys ( cachedData ?. ortb2 ?. user ?? { } ) . length > 0 )
184+ ) {
185+ config . log ( "info" , "No valid targeting data found" ) ;
186+ return { } ;
187+ }
188+
189+ config . log ( "info" , `Found targeting data with ${ cachedData . ortb2 . user . eids . length } EIDs` ) ;
190+ return cachedData ;
170191 }
171192
172- let targetingData = cachedData ;
193+ // Cache is empty and delay is configured - wait for event or timeout
194+ config . log ( "info" , `Waiting for targeting data (max ${ delay } ms)` ) ;
195+
196+ const targetingData = await new Promise < TargetingData | null > ( ( resolve ) => {
197+ let resolved = false ;
198+
199+ const eventHandler = ( ) => {
200+ if ( ! resolved ) {
201+ resolved = true ;
202+ config . log ( "info" , "Received optableResolved event" ) ;
203+ const data = targetingFromCache ( config ) ;
204+ resolve ( data ) ;
205+ }
206+ } ;
207+
208+ const timeoutId = setTimeout ( ( ) => {
209+ if ( ! resolved ) {
210+ resolved = true ;
211+ config . log ( "warn" , `Auction delay timeout (${ delay } ms) - no targeting data available` ) ;
212+ window . removeEventListener ( "optableResolved" , eventHandler ) ;
213+ resolve ( null ) ;
214+ }
215+ } , delay ) ;
216+
217+ window . addEventListener ( "optableResolved" , eventHandler , { once : true } ) ;
218+
219+ // Clean up timeout if event fires first
220+ window . addEventListener ( "optableResolved" , ( ) => clearTimeout ( timeoutId ) , { once : true } ) ;
221+ } ) ;
222+
223+ if ( ! targetingData ) {
224+ config . log ( "info" , "No targeting data available after waiting" ) ;
225+ return { } ;
226+ }
173227
174228 // Validate targeting data structure
175229 if ( ! targetingData ?. ortb2 ?. user ?. eids || ! Array . isArray ( targetingData ?. ortb2 ?. user ?. eids ) ) {
176230 config . log ( "info" , "No valid targeting data found" ) ;
177231 return { } ;
178232 }
179233
180- config . log ( "info" , `Found targeting data with ${ targetingData . ortb2 . user . eids . length } EIDs` ) ;
234+ config . log ( "info" , `Found targeting data with ${ targetingData . ortb2 . user . eids . length } EIDs after waiting ` ) ;
181235 return targetingData ;
182236}
183237
@@ -332,8 +386,9 @@ function buildRTD(options: RTDOptions = {}): RTDConfig {
332386 appendNewMergeStrategy,
333387 targetingFromCache,
334388 instance : options . instance ?? "instance" ,
389+ waitForTargeting : options . waitForTargeting ?? false ,
335390 async handleRtd ( reqBidsConfigObj : ReqBidsConfigObj , optableExtraData ?: any , mergeFn ?: any ) : Promise < void | null > {
336- const targetingData = options . targetingData ?? readTargetingData ( this ) ;
391+ const targetingData = options . targetingData ?? ( await readTargetingData ( this ) ) ;
337392 try {
338393 return handleRtd ( this , reqBidsConfigObj , targetingData , optableExtraData , mergeFn ) ;
339394 } catch ( error ) {
0 commit comments