@mixpeek/prebid 1.0.0 → 1.0.1

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 CHANGED
@@ -1,439 +1,317 @@
1
- # Mixpeek Contextual Adapter for Prebid.js
1
+
2
+ <p align="center">
3
+ <img src="assets/header.png" alt="Mixpeek Multimodal Contextual Targeting Adapter" />
4
+ </p>
5
+
6
+ # Mixpeek RTD (Real-Time Data) Adapter for Prebid.js
7
+
8
+ **This is a Real-Time Data (RTD) module for Prebid.js that replaces cookie-based targeting with sub-100ms contextual signals.**
2
9
 
3
10
  [![npm version](https://img.shields.io/npm/v/@mixpeek/prebid.svg)](https://www.npmjs.com/package/@mixpeek/prebid)
4
11
  [![npm downloads](https://img.shields.io/npm/dm/@mixpeek/prebid.svg)](https://www.npmjs.com/package/@mixpeek/prebid)
5
12
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
6
- [![Node Version](https://img.shields.io/node/v/@mixpeek/prebid.svg)](https://www.npmjs.com/package/@mixpeek/prebid)
7
13
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@mixpeek/prebid)](https://bundlephobia.com/package/@mixpeek/prebid)
8
- [![Dependencies](https://img.shields.io/librariesio/release/npm/@mixpeek/prebid)](https://www.npmjs.com/package/@mixpeek/prebid)
9
- [![GitHub Stars](https://img.shields.io/github/stars/mixpeek/prebid?style=social)](https://github.com/mixpeek/prebid)
10
- [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/mixpeek/prebid/pulls)
14
+ [![Status](https://img.shields.io/badge/Status-Production--Ready-brightgreen.svg)](https://www.npmjs.com/package/@mixpeek/prebid)
11
15
 
12
- ## 🎯 Overview
16
+ ---
13
17
 
14
- The Mixpeek Contextual Adapter enables publishers and SSPs using **Prebid.js** to enrich bid requests with real-time contextual data powered by Mixpeek's multimodal AI engine. This adapter provides:
18
+ ## What This Is
15
19
 
16
- - **Privacy-First Targeting**: No cookies, just content-based context
17
- - **Multimodal Analysis**: Text, images, video, and audio processing
18
- - **IAB Taxonomy**: Automatic classification into IAB content categories
19
- - **Brand Safety**: Real-time brand safety scoring
20
- - **Ad Adjacency Awareness**: Tracks previous ad to avoid repetition and improve user experience
21
- - **Sub-100ms Performance**: Optimized for header bidding speed requirements
22
- - **Graceful Fallbacks**: Never blocks the auction
20
+ | Type | Status |
21
+ |------|--------|
22
+ | **RTD Module** (bid enrichment) | Supported |
23
+ | Bidder Adapter | Not a bidder |
24
+ | Analytics Adapter | Not analytics |
25
+ | Identity Module | Not identity |
23
26
 
24
- ## 🚀 Quick Start
27
+ ---
25
28
 
26
- ### Installation
29
+ ## Why Use This
27
30
 
28
- ```bash
29
- npm install @mixpeek/prebid
30
- ```
31
+ 1. **Ad Adjacency Awareness** - Competitive separation, no repeat creatives
32
+ 2. **Privacy-First Contextual Targeting** - No cookies, no user tracking
33
+ 3. **IAB Taxonomy Classification** - Content categorization (v3.0)
34
+ 4. **Brand Safety Scoring** - Real-time sentiment analysis
35
+ 5. **Multimodal Analysis** - Text, image, video content understanding
36
+ 6. **Sub-100ms RTD Performance** - Optimized for header bidding latency
37
+
38
+ ---
31
39
 
32
- ### Basic Setup
40
+ ## Minimal Setup (Copy-Paste Ready)
33
41
 
34
42
  ```javascript
35
- // 1. Include the Mixpeek RTD module
36
43
  import '@mixpeek/prebid'
37
44
 
38
- // 2. Configure Mixpeek as an RTD provider
39
45
  pbjs.setConfig({
40
46
  realTimeData: {
41
- auctionDelay: 250, // Max time to wait for contextual data (ms)
42
47
  dataProviders: [{
43
48
  name: 'mixpeek',
44
- waitForIt: true, // Wait for Mixpeek before starting auction
45
49
  params: {
46
- apiKey: 'YOUR_MIXPEEK_API_KEY',
47
- collectionId: 'your-collection-id',
48
-
49
- // Use development server (temporary)
50
- endpoint: 'https://server-xb24.onrender.com',
51
- // Or production: endpoint: 'https://api.mixpeek.com',
52
-
53
- namespace: 'your-namespace', // optional
54
- featureExtractors: ['taxonomy', 'brand-safety'],
55
- mode: 'page', // 'page', 'video', or 'auto'
56
- timeout: 5000, // ms - higher for dev server
57
- cacheTTL: 300 // seconds
50
+ apiKey: 'YOUR_API_KEY',
51
+ collectionId: 'YOUR_COLLECTION_ID',
52
+ namespace: 'YOUR_NAMESPACE'
58
53
  }
59
54
  }]
60
55
  }
61
56
  })
62
-
63
- // 3. The RTD module automatically enriches bid requests!
64
- pbjs.requestBids({
65
- adUnits: [...],
66
- bidsBackHandler: function(bids) {
67
- // Bids now include Mixpeek contextual data in ortb2
68
- }
69
- })
70
57
  ```
71
58
 
72
- ## 📋 Prerequisites
73
-
74
- 1. **Mixpeek Account**: Sign up at [mixpeek.com](https://mixpeek.com/start)
75
- 2. **API Key**: Generate an API key in your Mixpeek dashboard
76
- 3. **Collection**: Create a collection with feature extractors configured
77
- 4. **Prebid.js**: Version 6.0.0 or higher
59
+ That's it. The RTD module automatically enriches all bid requests.
78
60
 
79
- ## 🔧 Configuration Options
61
+ ---
80
62
 
81
- ### RTD Configuration
63
+ ## Installation
82
64
 
83
- | Option | Type | Required | Default | Description |
84
- |--------|------|----------|---------|-------------|
85
- | `realTimeData.auctionDelay` | number | ❌ | 250 | Max time to wait for all RTD providers (ms) |
86
- | `realTimeData.dataProviders[].name` | string | ✅ | - | Must be `'mixpeek'` |
87
- | `realTimeData.dataProviders[].waitForIt` | boolean | ❌ | false | Wait for Mixpeek before starting auction |
88
-
89
- ### Mixpeek Parameters
65
+ ```bash
66
+ npm install @mixpeek/prebid
67
+ ```
90
68
 
91
- | Option | Type | Required | Default | Description |
92
- |--------|------|----------|---------|-------------|
93
- | `params.apiKey` | string | ✅ | - | Your Mixpeek API key |
94
- | `params.collectionId` | string | ✅ | - | Mixpeek collection ID for document processing |
95
- | `params.endpoint` | string | ❌ | `https://server-xb24.onrender.com` | Mixpeek API endpoint (dev server default) |
96
- | `params.namespace` | string | ❌ | - | Optional namespace for data isolation |
97
- | `params.featureExtractors` | array | ❌ | `['taxonomy']` | Feature extractors to use (taxonomy, brand-safety, etc.) |
98
- | `params.mode` | string | ❌ | `auto` | Content mode: `page`, `video`, `image`, or `auto` |
99
- | `params.timeout` | number | ❌ | 250 | API request timeout in milliseconds |
100
- | `params.cacheTTL` | number | ❌ | 300 | Cache TTL in seconds |
101
- | `params.enableCache` | boolean | ❌ | `true` | Enable local caching |
102
- | `params.debug` | boolean | ❌ | `false` | Enable debug logging |
103
- | `params.batchSize` | number | ❌ | 1 | Number of concurrent requests |
104
- | `params.retryAttempts` | number | ❌ | 2 | Number of retry attempts on failure |
69
+ ## Prerequisites
105
70
 
106
- ## 📊 Output: OpenRTB 2.6 Data Structure
71
+ 1. **Mixpeek Account** - Sign up at [mixpeek.com](https://mixpeek.com/start)
72
+ 2. **API Key** - Generate in your Mixpeek dashboard
73
+ 3. **Collection** - Create a collection with feature extractors
74
+ 4. **Namespace** - Your namespace ID (format: `ns_xxxxx`)
75
+ 5. **Prebid.js** - Version 6.0.0 or higher
107
76
 
108
- The RTD module injects contextual data into your bid requests using the OpenRTB 2.6 standard:
77
+ ---
109
78
 
110
- ### Site-Level Data (`ortb2.site.content`)
111
- ```javascript
112
- {
113
- "ortb2": {
114
- "site": {
115
- "content": {
116
- "cat": ["IAB19-11"], // IAB Content Categories
117
- "cattax": 6, // IAB Content Taxonomy v3.0
118
- "genre": "Technology - AI", // Human-readable category
119
- "keywords": "ai,technology,ml", // Extracted keywords
120
- "language": "en", // Content language
121
- "title": "Article Title", // Page title
122
- "url": "https://example.com", // Page URL
123
- "ext": {
124
- "data": {
125
- "mixpeek": {
126
- "score": 0.94, // Confidence score
127
- "brandSafety": 0.98, // Brand safety score
128
- "sentiment": "positive", // Content sentiment
129
- "embeddingId": "emb_abc123" // Embedding ID
130
- }
131
- }
132
- }
133
- }
134
- }
135
- }
136
- }
137
- ```
79
+ ## Full Configuration
138
80
 
139
- ### Impression-Level Data (`ortb2Imp.ext.data`)
140
81
  ```javascript
141
- {
142
- // Current page context
143
- "hb_mixpeek_taxonomy": "IAB19-11", // Primary IAB taxonomy code
144
- "hb_mixpeek_category": "Technology > AI", // Human-readable category
145
- "hb_mixpeek_node": "node_tech_ai", // Taxonomy node ID
146
- "hb_mixpeek_path": "tech/ai/ml", // Hierarchical path
147
- "hb_mixpeek_score": "0.94", // Confidence score
148
- "hb_mixpeek_safety": "0.98", // Brand safety score
149
- "hb_mixpeek_keywords": "AI,ML,tech", // Extracted keywords
150
- "hb_mixpeek_embed": "emb_abc123", // Embedding ID for retrieval
151
-
152
- // Previous ad context (adjacency awareness)
153
- "hb_mixpeek_prev_creative": "12345", // Last creative ID shown
154
- "hb_mixpeek_prev_bidder": "appnexus", // Last bidder that won
155
- "hb_mixpeek_prev_adunit": "sidebar-1", // Last ad unit code
156
- "hb_mixpeek_prev_cat": "IAB18-1,IAB12-3" // Last ad categories
157
- }
158
- ```
159
-
160
- ## 🎥 Usage Examples
161
-
162
- ### Page Context (Articles, Blogs)
82
+ import '@mixpeek/prebid'
163
83
 
164
- ```javascript
165
84
  pbjs.setConfig({
166
85
  realTimeData: {
167
- auctionDelay: 250,
86
+ auctionDelay: 250, // Max wait for contextual data (ms)
168
87
  dataProviders: [{
169
88
  name: 'mixpeek',
170
- waitForIt: true,
89
+ waitForIt: true, // Wait for Mixpeek before auction
171
90
  params: {
172
- apiKey: 'sk_your_api_key',
173
- collectionId: 'col_articles',
174
- mode: 'page',
175
- featureExtractors: ['taxonomy', 'brand-safety', 'keywords']
91
+ // Required
92
+ apiKey: 'YOUR_API_KEY',
93
+ collectionId: 'YOUR_COLLECTION_ID',
94
+ namespace: 'YOUR_NAMESPACE', // e.g., 'ns_abc123'
95
+
96
+ // Optional
97
+ endpoint: 'https://api.mixpeek.com', // Default
98
+ mode: 'auto', // 'page', 'video', 'image', or 'auto'
99
+ timeout: 250, // API timeout in ms
100
+ cacheTTL: 300, // Cache TTL in seconds
101
+ enableCache: true, // Enable local caching
102
+ debug: false // Enable debug logging
176
103
  }
177
104
  }]
178
105
  }
179
106
  })
180
- ```
181
-
182
- ### Video Context (Pre-roll, Mid-roll)
183
107
 
184
- ```javascript
185
- pbjs.setConfig({
186
- realTimeData: {
187
- auctionDelay: 300, // Longer delay for video processing
188
- dataProviders: [{
189
- name: 'mixpeek',
190
- waitForIt: true,
191
- params: {
192
- apiKey: 'sk_your_api_key',
193
- collectionId: 'col_videos',
194
- mode: 'video',
195
- videoSelector: '#main-video', // CSS selector for video element
196
- featureExtractors: ['taxonomy', 'scene-detection']
197
- }
198
- }]
108
+ // Bids are automatically enriched with contextual data
109
+ pbjs.requestBids({
110
+ adUnits: [...],
111
+ bidsBackHandler: function(bids) {
112
+ // Bids now include Mixpeek contextual data in ortb2
199
113
  }
200
114
  })
201
115
  ```
202
116
 
203
- ### Multi-Content Auto-Detection
117
+ ---
204
118
 
205
- ```javascript
206
- pbjs.setConfig({
207
- realTimeData: {
208
- auctionDelay: 250,
209
- dataProviders: [{
210
- name: 'mixpeek',
211
- waitForIt: true,
212
- params: {
213
- apiKey: 'sk_your_api_key',
214
- collectionId: 'col_mixed',
215
- mode: 'auto', // Automatically detects page, video, or image content
216
- featureExtractors: ['taxonomy', 'brand-safety', 'clustering']
217
- }
218
- }]
219
- }
220
- })
221
- ```
119
+ ## Ad Adjacency Awareness (Key Feature)
222
120
 
223
- ## 🏗️ How It Works
224
-
225
- ```mermaid
226
- sequenceDiagram
227
- participant Publisher
228
- participant Prebid
229
- participant MixpeekAdapter
230
- participant MixpeekAPI
231
- participant SSP
232
-
233
- Publisher->>Prebid: Request Bids
234
- Prebid->>MixpeekAdapter: beforeRequestBids event
235
- MixpeekAdapter->>MixpeekAdapter: Extract page/video content
236
- MixpeekAdapter->>MixpeekAdapter: Check cache
237
- alt Cache Miss
238
- MixpeekAdapter->>MixpeekAPI: POST /collections/{id}/documents
239
- MixpeekAPI->>MixpeekAPI: Process with feature extractors
240
- MixpeekAPI-->>MixpeekAdapter: Return enrichments
241
- MixpeekAdapter->>MixpeekAdapter: Cache result
242
- end
243
- MixpeekAdapter->>Prebid: Inject contextual key-values
244
- Prebid->>SSP: Send enriched bid request
245
- SSP-->>Prebid: Return bids
246
- Prebid-->>Publisher: Render ad
247
- ```
121
+ The adapter automatically tracks previously served ads to enable:
248
122
 
249
- ## 🧪 Testing
123
+ - **Competitive Separation** - Avoid showing competing brands consecutively
124
+ - **Creative Frequency** - Prevent the same ad from showing repeatedly
125
+ - **Category Diversity** - Improve ad variety for better user experience
250
126
 
251
- ```bash
252
- # Run all tests
253
- npm test
127
+ ### How SSPs/DSPs Use It
254
128
 
255
- # Run with coverage
256
- npm run test:coverage
129
+ ```javascript
130
+ // Data automatically injected into ortb2Imp.ext.data:
131
+ {
132
+ "hb_mixpeek_prev_creative": "12345", // Last creative ID
133
+ "hb_mixpeek_prev_bidder": "appnexus", // Last winning bidder
134
+ "hb_mixpeek_prev_adunit": "sidebar-1", // Last ad unit
135
+ "hb_mixpeek_prev_cat": "IAB18-1,IAB12-3" // Last ad categories
136
+ }
257
137
 
258
- # Watch mode
259
- npm run test:watch
138
+ // DSP can use for competitive separation:
139
+ if (prevCategories.includes('IAB18-1') && currentAd.category === 'IAB18-1') {
140
+ // Don't show competing fashion ads back-to-back
141
+ }
260
142
  ```
261
143
 
262
- ## 📖 Advanced Configuration
144
+ ### Privacy Safe
263
145
 
264
- ### Custom Feature Extractors
146
+ - No user tracking or identifiers
147
+ - Only ad metadata stored (< 200 bytes)
148
+ - Session-scoped, localStorage with memory fallback
149
+ - GDPR/CCPA compliant (contextual, not behavioral)
265
150
 
266
- ```javascript
267
- pbjs.setConfig({
268
- realTimeData: {
269
- auctionDelay: 250,
270
- dataProviders: [{
271
- name: 'mixpeek',
272
- waitForIt: true,
273
- params: {
274
- apiKey: 'sk_your_api_key',
275
- collectionId: 'col_custom',
276
- customExtractors: [
277
- {
278
- feature_extractor_id: 'sentiment-analyzer',
279
- payload: {
280
- model: 'sentiment-v2',
281
- threshold: 0.7
282
- }
283
- }
284
- ]
285
- }
286
- }]
287
- }
288
- })
289
- ```
151
+ ---
290
152
 
291
- ### Conditional Loading
153
+ ## OpenRTB 2.6 Output
154
+
155
+ ### Site-Level Data (`ortb2.site.content`)
292
156
 
293
157
  ```javascript
294
- // Only enrich on specific pages
295
- if (window.location.pathname.startsWith('/articles/')) {
296
- pbjs.setConfig({
297
- realTimeData: {
298
- auctionDelay: 250,
299
- dataProviders: [{
300
- name: 'mixpeek',
301
- waitForIt: true,
302
- params: {
303
- apiKey: 'sk_your_api_key',
304
- collectionId: 'col_articles',
305
- mode: 'page'
158
+ {
159
+ "site": {
160
+ "content": {
161
+ "cat": ["IAB19-11"], // IAB Content Categories
162
+ "cattax": 6, // IAB Taxonomy v3.0
163
+ "genre": "Technology", // Human-readable category
164
+ "keywords": "ai,technology,ml", // Extracted keywords
165
+ "language": "en", // Content language
166
+ "ext": {
167
+ "data": {
168
+ "mixpeek": {
169
+ "score": 0.94, // Classification confidence
170
+ "brandSafety": 0.98, // Brand safety score
171
+ "sentiment": "positive" // Content sentiment
172
+ }
306
173
  }
307
- }]
174
+ }
308
175
  }
309
- })
176
+ }
310
177
  }
311
178
  ```
312
179
 
313
- ### Event Callbacks
180
+ ### Impression-Level Keys (`ortb2Imp.ext.data`)
314
181
 
315
- ```javascript
316
- pbjs.onEvent('mixpeekContextReady', function(context) {
317
- console.log('Mixpeek context loaded:', context)
318
- // Custom analytics or modifications
319
- })
182
+ | Key | Description | Example |
183
+ |-----|-------------|---------|
184
+ | `hb_mixpeek_category` | Content category | `"Technology"` |
185
+ | `hb_mixpeek_score` | Classification confidence | `"0.94"` |
186
+ | `hb_mixpeek_safety` | Brand safety score | `"0.98"` |
187
+ | `hb_mixpeek_keywords` | Extracted keywords | `"AI,ML,tech"` |
188
+ | `hb_mixpeek_sentiment` | Content sentiment | `"positive"` |
189
+ | `hb_mixpeek_prev_creative` | Last creative ID | `"12345"` |
190
+ | `hb_mixpeek_prev_bidder` | Last winning bidder | `"appnexus"` |
191
+ | `hb_mixpeek_prev_cat` | Last ad categories | `"IAB18-1"` |
320
192
 
321
- pbjs.onEvent('mixpeekContextError', function(error) {
322
- console.error('Mixpeek context error:', error)
323
- // Custom error handling
324
- })
325
- ```
193
+ ---
326
194
 
327
- ## 🔄 Previous Ad Tracking (Adjacency Awareness)
195
+ ## How It Works
328
196
 
329
- The adapter automatically tracks the most recently served ad to enable adjacency-aware targeting. This helps:
197
+ ```
198
+ USER → WEBSITE → PREBID.JS
199
+
200
+ ├──→ MIXPEEK RTD Module
201
+ │ (Extract page content)
202
+ │ (Get previous ad info)
203
+ │ ↓
204
+ │ Returns: categories, keywords, sentiment
205
+ │ ↓
206
+ (enrich bid request with ortb2)
207
+
208
+ ├──→ SSP 1 ──→ DSPs (use contextual signals)
209
+ ├──→ SSP 2 ──→ DSPs (use adjacency data)
210
+ └──→ SSP N
211
+
212
+ (collect bids)
213
+
214
+
215
+ AD SERVER
216
+
217
+
218
+ RELEVANT AD
219
+ ```
330
220
 
331
- - **Avoid Ad Repetition**: Prevent showing the same creative or category repeatedly
332
- - **Frequency Capping**: Build frequency cap rules based on previous impressions
333
- - **Competitive Separation**: Avoid showing competing brands consecutively
334
- - **Enhanced User Experience**: Improve ad diversity and relevance
221
+ ---
335
222
 
336
- ### How It Works
223
+ ## Content Modes
337
224
 
338
- 1. **Automatic Tracking**: On every `bidResponse` event, the adapter stores minimal information about the winning ad
339
- 2. **Lightweight Storage**: Data is stored in memory + localStorage (privacy-safe, no PII)
340
- 3. **Targeting Keys**: Previous ad data is automatically injected into subsequent bid requests
225
+ ### Page Context (Default)
341
226
 
342
- ### Data Tracked
227
+ ```javascript
228
+ params: {
229
+ mode: 'page', // Analyze article/page content
230
+ // ...
231
+ }
232
+ ```
343
233
 
344
- | Field | Description | Example |
345
- |-------|-------------|---------|
346
- | `creativeId` | Winning creative ID | `"12345"` |
347
- | `bidder` | Winning bidder code | `"appnexus"` |
348
- | `adUnitCode` | Ad unit that served the ad | `"sidebar-1"` |
349
- | `categories` | IAB categories of the ad | `["IAB18-1", "IAB12-3"]` |
350
- | `timestamp` | When the ad was served | `1697123456789` |
234
+ ### Video Context
351
235
 
352
- ### Targeting Keys Injected
236
+ ```javascript
237
+ params: {
238
+ mode: 'video',
239
+ videoSelector: '#main-video', // CSS selector
240
+ // ...
241
+ }
242
+ ```
353
243
 
354
- The following keys are automatically added to `ortb2Imp.ext.data`:
244
+ ### Auto-Detection
355
245
 
356
- - `hb_mixpeek_prev_creative` - Last creative ID
357
- - `hb_mixpeek_prev_bidder` - Last winning bidder
358
- - `hb_mixpeek_prev_adunit` - Last ad unit code
359
- - `hb_mixpeek_prev_cat` - Last ad categories (comma-separated)
246
+ ```javascript
247
+ params: {
248
+ mode: 'auto', // Automatically detect content type
249
+ // ...
250
+ }
251
+ ```
360
252
 
361
- ### SSP/DSP Usage
253
+ ---
362
254
 
363
- SSPs and DSPs can use these keys for advanced targeting rules:
255
+ ## Event Callbacks
364
256
 
365
257
  ```javascript
366
- // Example: Avoid showing the same creative twice in a row
367
- if (bidRequest.ortb2Imp.ext.data.hb_mixpeek_prev_creative === currentCreative.id) {
368
- // Skip this creative or reduce bid
369
- }
370
-
371
- // Example: Competitive separation
372
- const prevCategories = bidRequest.ortb2Imp.ext.data.hb_mixpeek_prev_cat?.split(',') || []
373
- if (prevCategories.includes('IAB18-1') && currentAd.category === 'IAB18-1') {
374
- // Don't show competing fashion ads back-to-back
375
- }
376
- ```
258
+ // Context ready
259
+ pbjs.onEvent('mixpeekContextReady', function(context) {
260
+ console.log('Category:', context.taxonomy?.label)
261
+ console.log('Keywords:', context.keywords)
262
+ })
377
263
 
378
- ### Privacy & Storage
264
+ // Error handling
265
+ pbjs.onEvent('mixpeekContextError', function(error) {
266
+ // Errors don't block auction (graceful degradation)
267
+ console.error('Mixpeek error:', error)
268
+ })
379
269
 
380
- - **No User Tracking**: Only ad metadata is stored, no user identifiers or behavior
381
- - **Session-Scoped**: Data persists across page views within a session
382
- - **Local Storage**: Falls back to memory-only if localStorage is unavailable
383
- - **Minimal Data**: Only essential fields are stored (< 200 bytes)
384
- - **GDPR/CCPA Compliant**: No consent required as it doesn't track users
270
+ // Cache hit
271
+ pbjs.onEvent('mixpeekContextCached', function(data) {
272
+ console.log('Using cached context')
273
+ })
274
+ ```
385
275
 
386
- ### Programmatic Control
276
+ ---
387
277
 
388
- You can access the previous ad tracker directly if needed:
278
+ ## Testing
389
279
 
390
- ```javascript
391
- import previousAdTracker from '@mixpeek/prebid/utils/previousAdTracker'
280
+ ```bash
281
+ # Run all tests
282
+ npm test
392
283
 
393
- // Get last ad info
394
- const lastAd = previousAdTracker.getLast()
395
- console.log('Last creative:', lastAd?.creativeId)
284
+ # Run with live API (requires credentials)
285
+ MIXPEEK_API_KEY=your_key \
286
+ MIXPEEK_NAMESPACE=ns_xxxxx \
287
+ MIXPEEK_COLLECTION_ID=col_xxxxx \
288
+ npm run test:live
396
289
 
397
- // Clear history (e.g., on user logout or page type change)
398
- previousAdTracker.clear()
290
+ # Coverage report
291
+ npm run test:coverage
399
292
  ```
400
293
 
401
- ## 🔒 Security & Privacy
402
-
403
- - **No PII**: The adapter never sends user identifiers or cookies
404
- - **Content-Only**: Only page/video content is analyzed
405
- - **HTTPS**: All API calls use TLS encryption
406
- - **API Key Safety**: Store API keys securely (environment variables, server-side rendering)
407
- - **GDPR/CCPA Compliant**: Contextual targeting doesn't require user consent
294
+ ---
408
295
 
409
- ## 📚 Documentation
296
+ ## Documentation
410
297
 
411
- ### User Guides
412
298
  - [Quick Start](QUICKSTART.md) - Get running in 5 minutes
413
- - [Integration Guide](docs/integration-guide.md) - Step-by-step integration
414
- - [API Reference](docs/api-reference.md) - Complete API documentation
299
+ - [Integration Guide](docs/integration-guide.md) - Step-by-step setup
300
+ - [API Reference](docs/api-reference.md) - Complete API docs
415
301
  - [Testing Guide](TESTING.md) - How to test the adapter
416
- - [Endpoint Configuration](ENDPOINTS.md) - Configure API endpoints
417
- - [Health Check](docs/health-check.md) - Health check configuration
418
302
 
419
- ### Developer Resources
420
- - [Mixpeek API Docs](https://docs.mixpeek.com) - Platform documentation
421
- - [Internal Planning](tasks/) - Gap analysis & implementation plans (internal)
303
+ ---
422
304
 
423
- ## 🤝 Support
305
+ ## Support
424
306
 
425
- - **Email**: support@mixpeek.com
426
- - **GitHub Issues**: [Create an issue](https://github.com/mixpeek/prebid/issues)
427
307
  - **Documentation**: [docs.mixpeek.com](https://docs.mixpeek.com)
428
- - **Slack Community**: [Join our Slack](https://mixpeek.com/slack)
429
-
430
- ## 📄 License
431
-
432
- Apache 2.0 - see [LICENSE](LICENSE) file for details.
308
+ - **GitHub Issues**: [Create an issue](https://github.com/mixpeek/prebid/issues)
309
+ - **Email**: support@mixpeek.com
433
310
 
434
- ## 🙏 Credits
311
+ ---
435
312
 
436
- Built with ❤️ by [Mixpeek](https://mixpeek.com)
313
+ ## License
437
314
 
438
- Integrates with [Prebid.js](https://prebid.org) - an open-source header bidding solution
315
+ Apache 2.0 - see [LICENSE](LICENSE)
439
316
 
317
+ Built by [Mixpeek](https://mixpeek.com) | Integrates with [Prebid.js](https://prebid.org)