@bigcrunch/react-native-ads 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchAds.kt +434 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchBannerView.kt +484 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchInterstitial.kt +403 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/BigCrunchRewarded.kt +409 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/adapters/GoogleAdsAdapter.kt +592 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/AdOrchestrator.kt +623 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/AnalyticsClient.kt +719 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/BidRequestClient.kt +364 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/ConfigManager.kt +301 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/DeviceContext.kt +385 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/RewardedCallback.kt +42 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/core/SessionManager.kt +330 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/internal/DeviceHelper.kt +60 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/internal/HttpClient.kt +114 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Logger.kt +71 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/internal/PrivacyStore.kt +125 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/internal/Storage.kt +88 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/BannerAdListener.kt +55 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/InterstitialAdListener.kt +55 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/listeners/RewardedAdListener.kt +58 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/models/AdEvent.kt +880 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/models/AppConfig.kt +90 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/models/DeviceData.kt +18 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/models/PlacementConfig.kt +70 -0
- package/android/bigcrunch-ads/com/bigcrunch/ads/models/SessionInfo.kt +21 -0
- package/android/build.gradle +22 -10
- package/android/settings.gradle +2 -6
- package/ios/BigCrunchAds/Sources/Adapters/GoogleAdsAdapter.swift +512 -0
- package/ios/BigCrunchAds/Sources/BigCrunchAds.swift +387 -0
- package/ios/BigCrunchAds/Sources/BigCrunchBannerView.swift +448 -0
- package/ios/BigCrunchAds/Sources/BigCrunchInterstitial.swift +412 -0
- package/ios/BigCrunchAds/Sources/BigCrunchRewarded.swift +523 -0
- package/ios/BigCrunchAds/Sources/Core/AdOrchestrator.swift +514 -0
- package/ios/BigCrunchAds/Sources/Core/AnalyticsClient.swift +874 -0
- package/ios/BigCrunchAds/Sources/Core/BidRequestClient.swift +344 -0
- package/ios/BigCrunchAds/Sources/Core/ConfigManager.swift +306 -0
- package/ios/BigCrunchAds/Sources/Core/DeviceContext.swift +284 -0
- package/ios/BigCrunchAds/Sources/Core/SessionManager.swift +392 -0
- package/ios/BigCrunchAds/Sources/Internal/HTTPClient.swift +146 -0
- package/ios/BigCrunchAds/Sources/Internal/Logger.swift +62 -0
- package/ios/BigCrunchAds/Sources/Internal/PrivacyStore.swift +129 -0
- package/ios/BigCrunchAds/Sources/Internal/Storage.swift +73 -0
- package/ios/BigCrunchAds/Sources/Models/AdEvent.swift +784 -0
- package/ios/BigCrunchAds/Sources/Models/AppConfig.swift +100 -0
- package/ios/BigCrunchAds/Sources/Models/DeviceData.swift +68 -0
- package/ios/BigCrunchAds/Sources/Models/PlacementConfig.swift +137 -0
- package/ios/BigCrunchAds/Sources/Models/SessionInfo.swift +48 -0
- package/ios/BigCrunchAdsModule.swift +0 -1
- package/ios/BigCrunchBannerViewManager.swift +0 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -2
- package/package.json +8 -2
- package/react-native-bigcrunch-ads.podspec +0 -1
- package/scripts/inject-version.js +55 -0
- package/src/index.ts +3 -2
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// MARK: - Legacy Event (keeping for backward compatibility)
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Analytics event sent to BigCrunch backend
|
|
7
|
+
*
|
|
8
|
+
* All ad-related events (impressions, clicks, revenue) are tracked and sent
|
|
9
|
+
* to the analytics endpoint in this format.
|
|
10
|
+
*/
|
|
11
|
+
internal struct AdEvent: Codable {
|
|
12
|
+
let eventType: String // "screen_view", "ad_request", "ad_impression", "ad_revenue", "ad_click", "ad_viewable"
|
|
13
|
+
let placementId: String?
|
|
14
|
+
let format: String? // "banner", "interstitial", "rewarded"
|
|
15
|
+
let timestamp: Int64
|
|
16
|
+
let sessionId: String
|
|
17
|
+
let deviceInfo: DeviceInfo
|
|
18
|
+
let revenue: RevenueData?
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Device and app information included with every event
|
|
23
|
+
*/
|
|
24
|
+
internal struct DeviceInfo: Codable {
|
|
25
|
+
let platform: String
|
|
26
|
+
let osVersion: String
|
|
27
|
+
let appVersion: String
|
|
28
|
+
let deviceId: String
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Revenue data from ILRD (Impression-Level Revenue Data)
|
|
33
|
+
*
|
|
34
|
+
* Only present in ad_revenue events. Values are in micros (1/1,000,000 of currency unit).
|
|
35
|
+
*/
|
|
36
|
+
internal struct RevenueData: Codable {
|
|
37
|
+
let valueMicros: Int64
|
|
38
|
+
let currency: String
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// MARK: - Enhanced Analytics Events (matching web SDK data model)
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Screen/Page view event - matches `/pageviews` endpoint
|
|
45
|
+
*
|
|
46
|
+
* Sent when a new screen is viewed. Contains session context and device info.
|
|
47
|
+
*/
|
|
48
|
+
internal struct PageViewEvent: Codable {
|
|
49
|
+
// Web schema common fields
|
|
50
|
+
let payloadVersion: String // Must be semver format "x.y.z"
|
|
51
|
+
let configVersion: Int
|
|
52
|
+
let browserTimestamp: String // ISO 8601 with milliseconds
|
|
53
|
+
|
|
54
|
+
// Session/user context
|
|
55
|
+
let sessionId: String
|
|
56
|
+
let userId: String
|
|
57
|
+
let propertyId: String
|
|
58
|
+
let newUser: Bool
|
|
59
|
+
|
|
60
|
+
// Page context
|
|
61
|
+
let pageId: String
|
|
62
|
+
let sessionDepth: Int
|
|
63
|
+
let pageUrl: String // Must be valid URL or empty string (mobile uses empty)
|
|
64
|
+
let pageSearch: String // Query string, empty for mobile
|
|
65
|
+
let pageReferrer: String // Must be valid URL or empty string
|
|
66
|
+
|
|
67
|
+
// Device context (flattened)
|
|
68
|
+
let browser: String
|
|
69
|
+
let device: String
|
|
70
|
+
let os: String
|
|
71
|
+
let country: String
|
|
72
|
+
let region: String // Must be 2 chars or empty
|
|
73
|
+
|
|
74
|
+
// Attribution
|
|
75
|
+
let sessionSource: String
|
|
76
|
+
let sessionMedium: String
|
|
77
|
+
let utmSource: String
|
|
78
|
+
let utmMedium: String
|
|
79
|
+
let utmCampaign: String
|
|
80
|
+
let utmTerm: String
|
|
81
|
+
let utmContent: String
|
|
82
|
+
|
|
83
|
+
// Click IDs for attribution
|
|
84
|
+
let gclid: String
|
|
85
|
+
let fbclid: String
|
|
86
|
+
|
|
87
|
+
// Additional required fields
|
|
88
|
+
let acctType: String // "anonymous" for mobile
|
|
89
|
+
let diiSource: String // empty for mobile
|
|
90
|
+
let gamNetworkCode: String
|
|
91
|
+
let amznPubId: String // Must be valid UUID (nil UUID for empty)
|
|
92
|
+
let customDimensions: [String: String]
|
|
93
|
+
|
|
94
|
+
enum CodingKeys: String, CodingKey {
|
|
95
|
+
case payloadVersion = "payload_version"
|
|
96
|
+
case configVersion = "config_version"
|
|
97
|
+
case browserTimestamp = "browser_timestamp"
|
|
98
|
+
case sessionId = "session_id"
|
|
99
|
+
case userId = "user_id"
|
|
100
|
+
case propertyId = "property_id"
|
|
101
|
+
case newUser = "new_user"
|
|
102
|
+
case pageId = "page_id"
|
|
103
|
+
case sessionDepth = "session_depth"
|
|
104
|
+
case pageUrl = "page_url"
|
|
105
|
+
case pageSearch = "page_search"
|
|
106
|
+
case pageReferrer = "page_referrer"
|
|
107
|
+
case browser
|
|
108
|
+
case device
|
|
109
|
+
case os
|
|
110
|
+
case country
|
|
111
|
+
case region
|
|
112
|
+
case sessionSource = "session_source"
|
|
113
|
+
case sessionMedium = "session_medium"
|
|
114
|
+
case utmSource = "utm_source"
|
|
115
|
+
case utmMedium = "utm_medium"
|
|
116
|
+
case utmCampaign = "utm_campaign"
|
|
117
|
+
case utmTerm = "utm_term"
|
|
118
|
+
case utmContent = "utm_content"
|
|
119
|
+
case gclid
|
|
120
|
+
case fbclid
|
|
121
|
+
case acctType = "acct_type"
|
|
122
|
+
case diiSource = "dii_source"
|
|
123
|
+
case gamNetworkCode = "gam_network_code"
|
|
124
|
+
case amznPubId = "amzn_pub_id"
|
|
125
|
+
case customDimensions = "custom_dimensions"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Individual impression record - nested inside ImpressionBatchEvent
|
|
131
|
+
*
|
|
132
|
+
* Represents a single ad impression with auction/bid data.
|
|
133
|
+
*/
|
|
134
|
+
internal struct ImpressionRecord: Codable {
|
|
135
|
+
/// Placement identifier (slot_id in web SDK)
|
|
136
|
+
let slotId: String
|
|
137
|
+
|
|
138
|
+
/// GAM ad unit path
|
|
139
|
+
let gamUnit: String
|
|
140
|
+
|
|
141
|
+
/// GAM price bucket
|
|
142
|
+
let gamPriceBucket: String
|
|
143
|
+
|
|
144
|
+
/// Unique identifier for this impression
|
|
145
|
+
let impressionId: String
|
|
146
|
+
|
|
147
|
+
/// Auction ID (from Prebid) - REQUIRED, must be valid UUID
|
|
148
|
+
let auctionId: String
|
|
149
|
+
|
|
150
|
+
/// Refresh count for this placement
|
|
151
|
+
let refreshCount: Int
|
|
152
|
+
|
|
153
|
+
/// Winning bidder name
|
|
154
|
+
let adBidder: String
|
|
155
|
+
|
|
156
|
+
/// Ad size (e.g., "320x50")
|
|
157
|
+
let adSize: String
|
|
158
|
+
|
|
159
|
+
/// Bid price/revenue in CPM
|
|
160
|
+
let adPrice: Double
|
|
161
|
+
|
|
162
|
+
/// Floor price
|
|
163
|
+
let adFloorPrice: Double
|
|
164
|
+
|
|
165
|
+
/// Minimum bid to win
|
|
166
|
+
let minBidToWin: Double
|
|
167
|
+
|
|
168
|
+
/// Advertiser ID from GAM
|
|
169
|
+
let advertiserId: String
|
|
170
|
+
|
|
171
|
+
/// Campaign ID from GAM
|
|
172
|
+
let campaignId: String
|
|
173
|
+
|
|
174
|
+
/// Line item ID from GAM
|
|
175
|
+
let lineItemId: String
|
|
176
|
+
|
|
177
|
+
/// Creative ID from GAM response
|
|
178
|
+
let creativeId: String
|
|
179
|
+
|
|
180
|
+
/// Amazon bid data (if applicable)
|
|
181
|
+
let adAmznbid: String
|
|
182
|
+
|
|
183
|
+
/// Amazon price data (if applicable)
|
|
184
|
+
let adAmznp: String
|
|
185
|
+
|
|
186
|
+
/// Demand type (banner, video, etc.)
|
|
187
|
+
let adDemandType: String
|
|
188
|
+
|
|
189
|
+
/// Demand channel (e.g., "Prebid Header", "GAM Direct")
|
|
190
|
+
let demandChannel: String
|
|
191
|
+
|
|
192
|
+
/// Custom dimensions
|
|
193
|
+
let customDimensions: [String: String]
|
|
194
|
+
|
|
195
|
+
enum CodingKeys: String, CodingKey {
|
|
196
|
+
case slotId = "slot_id"
|
|
197
|
+
case gamUnit = "gam_unit"
|
|
198
|
+
case gamPriceBucket = "gam_price_bucket"
|
|
199
|
+
case impressionId = "impression_id"
|
|
200
|
+
case auctionId = "auction_id"
|
|
201
|
+
case refreshCount = "refresh_count"
|
|
202
|
+
case adBidder = "ad_bidder"
|
|
203
|
+
case adSize = "ad_size"
|
|
204
|
+
case adPrice = "ad_price"
|
|
205
|
+
case adFloorPrice = "ad_floor_price"
|
|
206
|
+
case minBidToWin = "min_bid_to_win"
|
|
207
|
+
case advertiserId = "advertiser_id"
|
|
208
|
+
case campaignId = "campaign_id"
|
|
209
|
+
case lineItemId = "line_item_id"
|
|
210
|
+
case creativeId = "creative_id"
|
|
211
|
+
case adAmznbid = "ad_amznbid"
|
|
212
|
+
case adAmznp = "ad_amznp"
|
|
213
|
+
case adDemandType = "ad_demand_type"
|
|
214
|
+
case demandChannel = "demand_channel"
|
|
215
|
+
case customDimensions = "custom_dimensions"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Impression batch event - matches `/impressions` endpoint
|
|
221
|
+
*
|
|
222
|
+
* Contains session/page context with nested array of impression records.
|
|
223
|
+
* This matches the web SDK format where impressions are batched with pageview context.
|
|
224
|
+
*/
|
|
225
|
+
internal struct ImpressionBatchEvent: Codable {
|
|
226
|
+
// Web schema common fields
|
|
227
|
+
let payloadVersion: String // Must be semver format "x.y.z"
|
|
228
|
+
let configVersion: Int
|
|
229
|
+
let browserTimestamp: String // ISO 8601 with milliseconds
|
|
230
|
+
|
|
231
|
+
// Session/user context
|
|
232
|
+
let sessionId: String
|
|
233
|
+
let userId: String
|
|
234
|
+
let propertyId: String
|
|
235
|
+
let newUser: Bool
|
|
236
|
+
let pageId: String
|
|
237
|
+
let sessionDepth: Int
|
|
238
|
+
|
|
239
|
+
// Page context
|
|
240
|
+
let pageUrl: String // Must be valid URL or empty string
|
|
241
|
+
let pageSearch: String
|
|
242
|
+
let pageReferrer: String
|
|
243
|
+
|
|
244
|
+
// Device context (flattened)
|
|
245
|
+
let browser: String
|
|
246
|
+
let device: String
|
|
247
|
+
let os: String
|
|
248
|
+
let country: String
|
|
249
|
+
let region: String // Must be 2 chars or empty
|
|
250
|
+
|
|
251
|
+
// Attribution
|
|
252
|
+
let sessionSource: String
|
|
253
|
+
let sessionMedium: String
|
|
254
|
+
let utmSource: String
|
|
255
|
+
let utmMedium: String
|
|
256
|
+
let utmCampaign: String
|
|
257
|
+
let utmTerm: String
|
|
258
|
+
let utmContent: String
|
|
259
|
+
|
|
260
|
+
// Click IDs for attribution
|
|
261
|
+
let gclid: String
|
|
262
|
+
let fbclid: String
|
|
263
|
+
|
|
264
|
+
// Additional required fields
|
|
265
|
+
let acctType: String
|
|
266
|
+
let diiSource: String
|
|
267
|
+
let gamNetworkCode: String
|
|
268
|
+
let amznPubId: String // Must be valid UUID (nil UUID for empty)
|
|
269
|
+
let customDimensions: [String: String]
|
|
270
|
+
|
|
271
|
+
// Nested impressions array
|
|
272
|
+
let impressions: [ImpressionRecord]
|
|
273
|
+
|
|
274
|
+
enum CodingKeys: String, CodingKey {
|
|
275
|
+
case payloadVersion = "payload_version"
|
|
276
|
+
case configVersion = "config_version"
|
|
277
|
+
case browserTimestamp = "browser_timestamp"
|
|
278
|
+
case sessionId = "session_id"
|
|
279
|
+
case userId = "user_id"
|
|
280
|
+
case propertyId = "property_id"
|
|
281
|
+
case newUser = "new_user"
|
|
282
|
+
case pageId = "page_id"
|
|
283
|
+
case sessionDepth = "session_depth"
|
|
284
|
+
case pageUrl = "page_url"
|
|
285
|
+
case pageSearch = "page_search"
|
|
286
|
+
case pageReferrer = "page_referrer"
|
|
287
|
+
case browser
|
|
288
|
+
case device
|
|
289
|
+
case os
|
|
290
|
+
case country
|
|
291
|
+
case region
|
|
292
|
+
case sessionSource = "session_source"
|
|
293
|
+
case sessionMedium = "session_medium"
|
|
294
|
+
case utmSource = "utm_source"
|
|
295
|
+
case utmMedium = "utm_medium"
|
|
296
|
+
case utmCampaign = "utm_campaign"
|
|
297
|
+
case utmTerm = "utm_term"
|
|
298
|
+
case utmContent = "utm_content"
|
|
299
|
+
case gclid
|
|
300
|
+
case fbclid
|
|
301
|
+
case acctType = "acct_type"
|
|
302
|
+
case diiSource = "dii_source"
|
|
303
|
+
case gamNetworkCode = "gam_network_code"
|
|
304
|
+
case amznPubId = "amzn_pub_id"
|
|
305
|
+
case customDimensions = "custom_dimensions"
|
|
306
|
+
case impressions
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Click data object nested inside ClickEvent
|
|
312
|
+
*
|
|
313
|
+
* Contains the click-specific fields per backend schema.
|
|
314
|
+
*/
|
|
315
|
+
internal struct ClickData: Codable {
|
|
316
|
+
/// Unique click identifier
|
|
317
|
+
let clickId: String
|
|
318
|
+
|
|
319
|
+
/// Placement identifier (slot_id in web SDK)
|
|
320
|
+
let slotId: String
|
|
321
|
+
|
|
322
|
+
/// Reference to the impression that was clicked - must be valid UUID
|
|
323
|
+
let impressionId: String
|
|
324
|
+
|
|
325
|
+
/// Refresh count for this placement
|
|
326
|
+
let refreshCount: Int
|
|
327
|
+
|
|
328
|
+
/// Amazon price data (if applicable)
|
|
329
|
+
let adAmznp: String
|
|
330
|
+
|
|
331
|
+
/// Winning bidder name
|
|
332
|
+
let adBidder: String
|
|
333
|
+
|
|
334
|
+
/// Ad size (e.g., "320x50")
|
|
335
|
+
let adSize: String
|
|
336
|
+
|
|
337
|
+
/// Advertiser ID from GAM
|
|
338
|
+
let advertiserId: String
|
|
339
|
+
|
|
340
|
+
/// Campaign ID from GAM
|
|
341
|
+
let campaignId: String
|
|
342
|
+
|
|
343
|
+
/// Line item ID from GAM
|
|
344
|
+
let lineItemId: String
|
|
345
|
+
|
|
346
|
+
/// Creative ID from GAM response
|
|
347
|
+
let creativeId: String
|
|
348
|
+
|
|
349
|
+
/// Demand type (banner, video, etc.)
|
|
350
|
+
let adDemandType: String
|
|
351
|
+
|
|
352
|
+
/// Demand channel (e.g., "Prebid Header", "GAM Direct")
|
|
353
|
+
let demandChannel: String
|
|
354
|
+
|
|
355
|
+
/// Custom dimensions - values must be string arrays per backend schema
|
|
356
|
+
let customDimensions: [String: [String]]
|
|
357
|
+
|
|
358
|
+
enum CodingKeys: String, CodingKey {
|
|
359
|
+
case clickId = "click_id"
|
|
360
|
+
case slotId = "slot_id"
|
|
361
|
+
case impressionId = "impression_id"
|
|
362
|
+
case refreshCount = "refresh_count"
|
|
363
|
+
case adAmznp = "ad_amznp"
|
|
364
|
+
case adBidder = "ad_bidder"
|
|
365
|
+
case adSize = "ad_size"
|
|
366
|
+
case advertiserId = "advertiser_id"
|
|
367
|
+
case campaignId = "campaign_id"
|
|
368
|
+
case lineItemId = "line_item_id"
|
|
369
|
+
case creativeId = "creative_id"
|
|
370
|
+
case adDemandType = "ad_demand_type"
|
|
371
|
+
case demandChannel = "demand_channel"
|
|
372
|
+
case customDimensions = "custom_dimensions"
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Ad click event - matches `/clicks` endpoint
|
|
378
|
+
*
|
|
379
|
+
* Sent when a user clicks on an ad.
|
|
380
|
+
*/
|
|
381
|
+
internal struct ClickEvent: Codable {
|
|
382
|
+
// Web schema common fields
|
|
383
|
+
let payloadVersion: String // Must be semver format "x.y.z"
|
|
384
|
+
let configVersion: Int
|
|
385
|
+
let browserTimestamp: String // ISO 8601 with milliseconds
|
|
386
|
+
|
|
387
|
+
// Session/user context
|
|
388
|
+
let sessionId: String
|
|
389
|
+
let userId: String
|
|
390
|
+
let propertyId: String
|
|
391
|
+
let newUser: Bool
|
|
392
|
+
let pageId: String
|
|
393
|
+
let sessionDepth: Int
|
|
394
|
+
|
|
395
|
+
// Page context
|
|
396
|
+
let pageUrl: String
|
|
397
|
+
let pageSearch: String
|
|
398
|
+
let pageReferrer: String
|
|
399
|
+
|
|
400
|
+
// Device context (flattened)
|
|
401
|
+
let browser: String
|
|
402
|
+
let device: String
|
|
403
|
+
let os: String
|
|
404
|
+
let country: String
|
|
405
|
+
let region: String // Must be 2 chars or empty
|
|
406
|
+
|
|
407
|
+
// Attribution
|
|
408
|
+
let sessionSource: String
|
|
409
|
+
let sessionMedium: String
|
|
410
|
+
let utmSource: String
|
|
411
|
+
let utmMedium: String
|
|
412
|
+
let utmCampaign: String
|
|
413
|
+
let utmTerm: String
|
|
414
|
+
let utmContent: String
|
|
415
|
+
|
|
416
|
+
// Click IDs
|
|
417
|
+
let gclid: String
|
|
418
|
+
let fbclid: String
|
|
419
|
+
|
|
420
|
+
// Additional required fields
|
|
421
|
+
let acctType: String
|
|
422
|
+
let diiSource: String
|
|
423
|
+
let gamNetworkCode: String
|
|
424
|
+
let amznPubId: String
|
|
425
|
+
let customDimensions: [String: String]
|
|
426
|
+
|
|
427
|
+
// Click-specific fields (nested click object per schema)
|
|
428
|
+
let click: ClickData
|
|
429
|
+
|
|
430
|
+
enum CodingKeys: String, CodingKey {
|
|
431
|
+
case payloadVersion = "payload_version"
|
|
432
|
+
case configVersion = "config_version"
|
|
433
|
+
case browserTimestamp = "browser_timestamp"
|
|
434
|
+
case sessionId = "session_id"
|
|
435
|
+
case userId = "user_id"
|
|
436
|
+
case propertyId = "property_id"
|
|
437
|
+
case newUser = "new_user"
|
|
438
|
+
case pageId = "page_id"
|
|
439
|
+
case sessionDepth = "session_depth"
|
|
440
|
+
case pageUrl = "page_url"
|
|
441
|
+
case pageSearch = "page_search"
|
|
442
|
+
case pageReferrer = "page_referrer"
|
|
443
|
+
case browser
|
|
444
|
+
case device
|
|
445
|
+
case os
|
|
446
|
+
case country
|
|
447
|
+
case region
|
|
448
|
+
case sessionSource = "session_source"
|
|
449
|
+
case sessionMedium = "session_medium"
|
|
450
|
+
case utmSource = "utm_source"
|
|
451
|
+
case utmMedium = "utm_medium"
|
|
452
|
+
case utmCampaign = "utm_campaign"
|
|
453
|
+
case utmTerm = "utm_term"
|
|
454
|
+
case utmContent = "utm_content"
|
|
455
|
+
case gclid
|
|
456
|
+
case fbclid
|
|
457
|
+
case acctType = "acct_type"
|
|
458
|
+
case diiSource = "dii_source"
|
|
459
|
+
case gamNetworkCode = "gam_network_code"
|
|
460
|
+
case amznPubId = "amzn_pub_id"
|
|
461
|
+
case customDimensions = "custom_dimensions"
|
|
462
|
+
case click
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Viewability data object nested inside ViewabilityEvent
|
|
468
|
+
*
|
|
469
|
+
* Contains the per-slot viewability metrics.
|
|
470
|
+
*/
|
|
471
|
+
internal struct ViewabilityData: Codable {
|
|
472
|
+
/// Placement identifier (slot_id in web SDK)
|
|
473
|
+
let slotId: String
|
|
474
|
+
|
|
475
|
+
/// Reference to the impression - must be valid UUID
|
|
476
|
+
let impressionId: String
|
|
477
|
+
|
|
478
|
+
/// Refresh count for this placement
|
|
479
|
+
let refreshCount: Int
|
|
480
|
+
|
|
481
|
+
/// Amazon price data (if applicable)
|
|
482
|
+
let adAmznp: String
|
|
483
|
+
|
|
484
|
+
/// Winning bidder name
|
|
485
|
+
let adBidder: String
|
|
486
|
+
|
|
487
|
+
/// Ad size (e.g., "320x50")
|
|
488
|
+
let adSize: String
|
|
489
|
+
|
|
490
|
+
/// Advertiser ID from GAM
|
|
491
|
+
let advertiserId: String
|
|
492
|
+
|
|
493
|
+
/// Campaign ID from GAM
|
|
494
|
+
let campaignId: String
|
|
495
|
+
|
|
496
|
+
/// Line item ID from GAM
|
|
497
|
+
let lineItemId: String
|
|
498
|
+
|
|
499
|
+
/// Creative ID from GAM response
|
|
500
|
+
let creativeId: String
|
|
501
|
+
|
|
502
|
+
/// Demand type (banner, video, etc.)
|
|
503
|
+
let adDemandType: String
|
|
504
|
+
|
|
505
|
+
/// Demand channel (e.g., "Prebid Header", "GAM Direct")
|
|
506
|
+
let demandChannel: String
|
|
507
|
+
|
|
508
|
+
/// Custom dimensions
|
|
509
|
+
let customDimensions: [String: [String]]
|
|
510
|
+
|
|
511
|
+
enum CodingKeys: String, CodingKey {
|
|
512
|
+
case slotId = "slot_id"
|
|
513
|
+
case impressionId = "impression_id"
|
|
514
|
+
case refreshCount = "refresh_count"
|
|
515
|
+
case adAmznp = "ad_amznp"
|
|
516
|
+
case adBidder = "ad_bidder"
|
|
517
|
+
case adSize = "ad_size"
|
|
518
|
+
case advertiserId = "advertiser_id"
|
|
519
|
+
case campaignId = "campaign_id"
|
|
520
|
+
case lineItemId = "line_item_id"
|
|
521
|
+
case creativeId = "creative_id"
|
|
522
|
+
case adDemandType = "ad_demand_type"
|
|
523
|
+
case demandChannel = "demand_channel"
|
|
524
|
+
case customDimensions = "custom_dimensions"
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Viewability event - matches `/viewability` endpoint
|
|
530
|
+
*
|
|
531
|
+
* Sent when an ad meets viewability thresholds (e.g., 50% visible for 1 second).
|
|
532
|
+
* Contains session/page context with nested viewability array.
|
|
533
|
+
*/
|
|
534
|
+
internal struct ViewabilityEvent: Codable {
|
|
535
|
+
// Web schema common fields
|
|
536
|
+
let payloadVersion: String // Must be semver format "x.y.z"
|
|
537
|
+
let configVersion: Int
|
|
538
|
+
let browserTimestamp: String // ISO 8601 with milliseconds
|
|
539
|
+
|
|
540
|
+
// Session/user context
|
|
541
|
+
let sessionId: String
|
|
542
|
+
let userId: String
|
|
543
|
+
let propertyId: String
|
|
544
|
+
let newUser: Bool
|
|
545
|
+
let pageId: String
|
|
546
|
+
let sessionDepth: Int
|
|
547
|
+
|
|
548
|
+
// Page context
|
|
549
|
+
let pageUrl: String
|
|
550
|
+
let pageSearch: String
|
|
551
|
+
let pageReferrer: String
|
|
552
|
+
|
|
553
|
+
// Device context (flattened)
|
|
554
|
+
let browser: String
|
|
555
|
+
let device: String
|
|
556
|
+
let os: String
|
|
557
|
+
let country: String
|
|
558
|
+
let region: String // Must be 2 chars or empty
|
|
559
|
+
|
|
560
|
+
// Attribution
|
|
561
|
+
let sessionSource: String
|
|
562
|
+
let sessionMedium: String
|
|
563
|
+
let utmSource: String
|
|
564
|
+
let utmMedium: String
|
|
565
|
+
let utmCampaign: String
|
|
566
|
+
let utmTerm: String
|
|
567
|
+
let utmContent: String
|
|
568
|
+
|
|
569
|
+
// Click IDs
|
|
570
|
+
let gclid: String
|
|
571
|
+
let fbclid: String
|
|
572
|
+
|
|
573
|
+
// Additional required fields
|
|
574
|
+
let acctType: String
|
|
575
|
+
let diiSource: String
|
|
576
|
+
let gamNetworkCode: String
|
|
577
|
+
let amznPubId: String
|
|
578
|
+
|
|
579
|
+
// Nested viewability array (per backend schema)
|
|
580
|
+
let viewability: [ViewabilityData]
|
|
581
|
+
|
|
582
|
+
enum CodingKeys: String, CodingKey {
|
|
583
|
+
case payloadVersion = "payload_version"
|
|
584
|
+
case configVersion = "config_version"
|
|
585
|
+
case browserTimestamp = "browser_timestamp"
|
|
586
|
+
case sessionId = "session_id"
|
|
587
|
+
case userId = "user_id"
|
|
588
|
+
case propertyId = "property_id"
|
|
589
|
+
case newUser = "new_user"
|
|
590
|
+
case pageId = "page_id"
|
|
591
|
+
case sessionDepth = "session_depth"
|
|
592
|
+
case pageUrl = "page_url"
|
|
593
|
+
case pageSearch = "page_search"
|
|
594
|
+
case pageReferrer = "page_referrer"
|
|
595
|
+
case browser
|
|
596
|
+
case device
|
|
597
|
+
case os
|
|
598
|
+
case country
|
|
599
|
+
case region
|
|
600
|
+
case sessionSource = "session_source"
|
|
601
|
+
case sessionMedium = "session_medium"
|
|
602
|
+
case utmSource = "utm_source"
|
|
603
|
+
case utmMedium = "utm_medium"
|
|
604
|
+
case utmCampaign = "utm_campaign"
|
|
605
|
+
case utmTerm = "utm_term"
|
|
606
|
+
case utmContent = "utm_content"
|
|
607
|
+
case gclid
|
|
608
|
+
case fbclid
|
|
609
|
+
case acctType = "acct_type"
|
|
610
|
+
case diiSource = "dii_source"
|
|
611
|
+
case gamNetworkCode = "gam_network_code"
|
|
612
|
+
case amznPubId = "amzn_pub_id"
|
|
613
|
+
case viewability
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/**
|
|
618
|
+
* Engagement event - matches `/engagement` endpoint
|
|
619
|
+
*
|
|
620
|
+
* Tracks user engagement with content/screens.
|
|
621
|
+
*/
|
|
622
|
+
internal struct EngagementEvent: Codable {
|
|
623
|
+
// Web schema common fields
|
|
624
|
+
let payloadVersion: String // Must be semver format "x.y.z"
|
|
625
|
+
let configVersion: Int
|
|
626
|
+
let browserTimestamp: String // ISO 8601 with milliseconds
|
|
627
|
+
|
|
628
|
+
// Session/user context
|
|
629
|
+
let sessionId: String
|
|
630
|
+
let userId: String
|
|
631
|
+
let propertyId: String
|
|
632
|
+
let newUser: Bool
|
|
633
|
+
let pageId: String
|
|
634
|
+
let sessionDepth: Int
|
|
635
|
+
|
|
636
|
+
// Page context
|
|
637
|
+
let pageUrl: String
|
|
638
|
+
let pageSearch: String
|
|
639
|
+
let pageReferrer: String
|
|
640
|
+
|
|
641
|
+
// Device context (flattened)
|
|
642
|
+
let browser: String
|
|
643
|
+
let device: String
|
|
644
|
+
let os: String
|
|
645
|
+
let country: String
|
|
646
|
+
let region: String // Must be 2 chars or empty
|
|
647
|
+
|
|
648
|
+
// Attribution
|
|
649
|
+
let sessionSource: String
|
|
650
|
+
let sessionMedium: String
|
|
651
|
+
let utmSource: String
|
|
652
|
+
let utmMedium: String
|
|
653
|
+
let utmCampaign: String
|
|
654
|
+
let utmTerm: String
|
|
655
|
+
let utmContent: String
|
|
656
|
+
|
|
657
|
+
// Click IDs
|
|
658
|
+
let gclid: String
|
|
659
|
+
let fbclid: String
|
|
660
|
+
|
|
661
|
+
// Additional required fields
|
|
662
|
+
let acctType: String
|
|
663
|
+
let diiSource: String
|
|
664
|
+
let gamNetworkCode: String
|
|
665
|
+
let amznPubId: String
|
|
666
|
+
|
|
667
|
+
/// Custom dimensions - values must be string arrays per backend schema
|
|
668
|
+
let customDimensions: [String: [String]]
|
|
669
|
+
|
|
670
|
+
// Engagement-specific fields
|
|
671
|
+
/// Time actively engaged in seconds
|
|
672
|
+
let engagedTime: Int
|
|
673
|
+
|
|
674
|
+
/// Total time on page/screen in seconds
|
|
675
|
+
let timeOnPage: Int
|
|
676
|
+
|
|
677
|
+
/// Maximum scroll depth percentage (0-100)
|
|
678
|
+
let scrollDepth: Int
|
|
679
|
+
|
|
680
|
+
enum CodingKeys: String, CodingKey {
|
|
681
|
+
case payloadVersion = "payload_version"
|
|
682
|
+
case configVersion = "config_version"
|
|
683
|
+
case browserTimestamp = "browser_timestamp"
|
|
684
|
+
case sessionId = "session_id"
|
|
685
|
+
case userId = "user_id"
|
|
686
|
+
case propertyId = "property_id"
|
|
687
|
+
case newUser = "new_user"
|
|
688
|
+
case pageId = "page_id"
|
|
689
|
+
case sessionDepth = "session_depth"
|
|
690
|
+
case pageUrl = "page_url"
|
|
691
|
+
case pageSearch = "page_search"
|
|
692
|
+
case pageReferrer = "page_referrer"
|
|
693
|
+
case browser
|
|
694
|
+
case device
|
|
695
|
+
case os
|
|
696
|
+
case country
|
|
697
|
+
case region
|
|
698
|
+
case sessionSource = "session_source"
|
|
699
|
+
case sessionMedium = "session_medium"
|
|
700
|
+
case utmSource = "utm_source"
|
|
701
|
+
case utmMedium = "utm_medium"
|
|
702
|
+
case utmCampaign = "utm_campaign"
|
|
703
|
+
case utmTerm = "utm_term"
|
|
704
|
+
case utmContent = "utm_content"
|
|
705
|
+
case gclid
|
|
706
|
+
case fbclid
|
|
707
|
+
case acctType = "acct_type"
|
|
708
|
+
case diiSource = "dii_source"
|
|
709
|
+
case gamNetworkCode = "gam_network_code"
|
|
710
|
+
case amznPubId = "amzn_pub_id"
|
|
711
|
+
case customDimensions = "custom_dimensions"
|
|
712
|
+
case engagedTime = "engaged_time"
|
|
713
|
+
case timeOnPage = "time_on_page"
|
|
714
|
+
case scrollDepth = "scroll_depth"
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// MARK: - Auction Data
|
|
719
|
+
|
|
720
|
+
/**
|
|
721
|
+
* Auction data from Prebid response
|
|
722
|
+
*
|
|
723
|
+
* Captures bidding information for analytics.
|
|
724
|
+
*/
|
|
725
|
+
internal struct AuctionData {
|
|
726
|
+
/// Prebid auction ID
|
|
727
|
+
let auctionId: String?
|
|
728
|
+
|
|
729
|
+
/// Winning bidder name
|
|
730
|
+
let bidder: String?
|
|
731
|
+
|
|
732
|
+
/// Winning bid price in CPM
|
|
733
|
+
let bidPriceCpm: Double?
|
|
734
|
+
|
|
735
|
+
/// Creative ID from winning bid
|
|
736
|
+
let creativeId: String?
|
|
737
|
+
|
|
738
|
+
/// Empty auction data
|
|
739
|
+
static let empty = AuctionData(auctionId: nil, bidder: nil, bidPriceCpm: nil, creativeId: nil)
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// MARK: - Impression Context
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Context for tracking an ad impression
|
|
746
|
+
*
|
|
747
|
+
* Aggregates all data needed to track an impression through its lifecycle.
|
|
748
|
+
*/
|
|
749
|
+
internal struct ImpressionContext {
|
|
750
|
+
/// Unique impression identifier
|
|
751
|
+
let impressionId: String
|
|
752
|
+
|
|
753
|
+
/// Placement configuration
|
|
754
|
+
let placementId: String
|
|
755
|
+
let gamAdUnit: String
|
|
756
|
+
let format: String
|
|
757
|
+
|
|
758
|
+
/// Size (for banners)
|
|
759
|
+
let width: Int?
|
|
760
|
+
let height: Int?
|
|
761
|
+
|
|
762
|
+
/// Auction data (populated after Prebid response)
|
|
763
|
+
var auctionData: AuctionData
|
|
764
|
+
|
|
765
|
+
/// Timestamp when impression was created
|
|
766
|
+
let createdAt: Int64
|
|
767
|
+
|
|
768
|
+
init(
|
|
769
|
+
placementId: String,
|
|
770
|
+
gamAdUnit: String,
|
|
771
|
+
format: String,
|
|
772
|
+
width: Int? = nil,
|
|
773
|
+
height: Int? = nil
|
|
774
|
+
) {
|
|
775
|
+
self.impressionId = UUID().uuidString
|
|
776
|
+
self.placementId = placementId
|
|
777
|
+
self.gamAdUnit = gamAdUnit
|
|
778
|
+
self.format = format
|
|
779
|
+
self.width = width
|
|
780
|
+
self.height = height
|
|
781
|
+
self.auctionData = .empty
|
|
782
|
+
self.createdAt = Int64(Date().timeIntervalSince1970 * 1000)
|
|
783
|
+
}
|
|
784
|
+
}
|