@mixpeek/prebid 1.0.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.
@@ -0,0 +1,577 @@
1
+ # Mixpeek Context Adapter - Integration Guide
2
+
3
+ This guide will walk you through integrating the Mixpeek Context Adapter with Prebid.js.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Prerequisites](#prerequisites)
8
+ 2. [Installation](#installation)
9
+ 3. [Configuration](#configuration)
10
+ 4. [Testing](#testing)
11
+ 5. [Deployment](#deployment)
12
+ 6. [Troubleshooting](#troubleshooting)
13
+
14
+ ## Prerequisites
15
+
16
+ Before you begin, make sure you have:
17
+
18
+ - **Mixpeek Account**: Sign up at [mixpeek.com/start](https://mixpeek.com/start)
19
+ - **API Key**: Generate an API key from your Mixpeek dashboard
20
+ - **Collection**: Create a collection with feature extractors configured
21
+ - **Prebid.js**: Version 6.0.0 or higher installed on your site
22
+
23
+ ### Setting Up Your Mixpeek Collection
24
+
25
+ 1. **Create a Collection**:
26
+ ```bash
27
+ curl -X POST https://api.mixpeek.com/v1/collections \
28
+ -H "Authorization: Bearer YOUR_API_KEY" \
29
+ -H "Content-Type: application/json" \
30
+ -d '{
31
+ "name": "contextual-targeting",
32
+ "description": "Collection for contextual ad targeting"
33
+ }'
34
+ ```
35
+
36
+ 2. **Note your Collection ID** from the response (e.g., `col_abc123`)
37
+
38
+ 3. **Verify Feature Extractors** are available:
39
+ ```bash
40
+ curl https://api.mixpeek.com/v1/collections/features/extractors \
41
+ -H "Authorization: Bearer YOUR_API_KEY"
42
+ ```
43
+
44
+ ## Installation
45
+
46
+ ### Option 1: NPM (Recommended)
47
+
48
+ ```bash
49
+ npm install @mixpeek/prebid-contextual-adapter
50
+ ```
51
+
52
+ Then include in your JavaScript:
53
+
54
+ ```javascript
55
+ import '@mixpeek/prebid-contextual-adapter'
56
+ ```
57
+
58
+ ### Option 2: CDN
59
+
60
+ ```html
61
+ <script src="https://cdn.jsdelivr.net/npm/@mixpeek/prebid-contextual-adapter@latest/dist/mixpeekContextAdapter.js"></script>
62
+ ```
63
+
64
+ ### Option 3: Download
65
+
66
+ Download the latest release from [GitHub releases](https://github.com/mixpeek/prebid-contextual-adapter/releases) and include it in your page:
67
+
68
+ ```html
69
+ <script src="/path/to/mixpeekContextAdapter.js"></script>
70
+ ```
71
+
72
+ ## Configuration
73
+
74
+ ### Basic Setup
75
+
76
+ Add the Mixpeek RTD configuration to your Prebid setup:
77
+
78
+ ```javascript
79
+ var pbjs = pbjs || {};
80
+ pbjs.que = pbjs.que || [];
81
+
82
+ pbjs.que.push(function() {
83
+ // Configure Mixpeek as an RTD provider
84
+ pbjs.setConfig({
85
+ realTimeData: {
86
+ auctionDelay: 250, // Max time to wait for RTD providers
87
+ dataProviders: [{
88
+ name: 'mixpeek',
89
+ waitForIt: true, // Wait for Mixpeek before starting auction
90
+ params: {
91
+ apiKey: 'sk_your_api_key_here',
92
+ collectionId: 'col_your_collection_id',
93
+ featureExtractors: ['taxonomy'],
94
+ mode: 'auto',
95
+ timeout: 250,
96
+ cacheTTL: 300
97
+ }
98
+ }]
99
+ }
100
+ });
101
+
102
+ // Add your ad units
103
+ pbjs.addAdUnits([...]);
104
+
105
+ // Request bids
106
+ pbjs.requestBids({...});
107
+ });
108
+ ```
109
+
110
+ ### Health Check Configuration
111
+
112
+ The adapter includes smart health check functionality:
113
+
114
+ ```javascript
115
+ pbjs.setConfig({
116
+ realTimeData: {
117
+ auctionDelay: 250,
118
+ dataProviders: [{
119
+ name: 'mixpeek',
120
+ waitForIt: true,
121
+ params: {
122
+ apiKey: 'sk_your_api_key_here',
123
+ collectionId: 'col_your_collection_id',
124
+
125
+ // Health check modes:
126
+ healthCheck: 'lazy', // Default - check on first request (recommended)
127
+ // healthCheck: 'eager', // Check immediately on init (adds ~200-500ms)
128
+ // healthCheck: false, // Skip health check (max performance)
129
+ }
130
+ }]
131
+ }
132
+ });
133
+ ```
134
+
135
+ **Recommended:** Use `lazy` (default) for production - validates API without impacting page load.
136
+
137
+ See [Health Check Documentation](health-check.md) for details.
138
+
139
+ ### Advanced Configuration
140
+
141
+ For more control, use the full configuration object:
142
+
143
+ ```javascript
144
+ pbjs.setConfig({
145
+ realTimeData: {
146
+ auctionDelay: 250, // Max time to wait for all RTD providers
147
+ dataProviders: [{
148
+ name: 'mixpeek',
149
+ waitForIt: true, // Wait for this provider before auction
150
+ params: {
151
+ // Required
152
+ apiKey: 'sk_your_api_key_here',
153
+ collectionId: 'col_your_collection_id',
154
+
155
+ // Optional
156
+ endpoint: 'https://api.mixpeek.com',
157
+ namespace: 'production',
158
+
159
+ // Content extraction
160
+ mode: 'auto', // 'auto', 'page', 'video', or 'image'
161
+ videoSelector: 'video', // CSS selector for video elements
162
+ maxImages: 5, // Max images to analyze
163
+
164
+ // Feature extractors
165
+ featureExtractors: [
166
+ 'taxonomy',
167
+ 'brand-safety',
168
+ 'keywords',
169
+ 'sentiment'
170
+ ],
171
+
172
+ // Or with custom configuration
173
+ customExtractors: [
174
+ {
175
+ feature_extractor_id: 'taxonomy',
176
+ payload: {
177
+ version: '3.0',
178
+ threshold: 0.7
179
+ }
180
+ }
181
+ ],
182
+
183
+ // Performance
184
+ timeout: 250, // ms
185
+ retryAttempts: 2,
186
+
187
+ // Caching
188
+ enableCache: true,
189
+ cacheTTL: 300, // seconds
190
+
191
+ // Debugging
192
+ debug: false
193
+ }
194
+ }]
195
+ }
196
+ });
197
+ ```
198
+
199
+ ## Integration Patterns
200
+
201
+ ### Pattern 1: Page-Level Context (Default)
202
+
203
+ Best for article pages, blog posts, and content sites:
204
+
205
+ ```javascript
206
+ pbjs.setConfig({
207
+ realTimeData: {
208
+ auctionDelay: 250,
209
+ dataProviders: [{
210
+ name: 'mixpeek',
211
+ waitForIt: true,
212
+ params: {
213
+ apiKey: 'sk_...',
214
+ collectionId: 'col_...',
215
+ mode: 'page',
216
+ featureExtractors: ['taxonomy', 'brand-safety']
217
+ }
218
+ }]
219
+ }
220
+ });
221
+ ```
222
+
223
+ The adapter will automatically extract:
224
+ - Page URL and title
225
+ - Meta descriptions and keywords
226
+ - Body text content
227
+ - Open Graph tags
228
+ - Structured data (JSON-LD)
229
+
230
+ ### Pattern 2: Video Context
231
+
232
+ For video content pages or video players:
233
+
234
+ ```javascript
235
+ pbjs.setConfig({
236
+ realTimeData: {
237
+ auctionDelay: 300, // Longer delay for video processing
238
+ dataProviders: [{
239
+ name: 'mixpeek',
240
+ waitForIt: true,
241
+ params: {
242
+ apiKey: 'sk_...',
243
+ collectionId: 'col_...',
244
+ mode: 'video',
245
+ videoSelector: '#main-video', // Specific video element
246
+ featureExtractors: ['taxonomy', 'scene-detection']
247
+ }
248
+ }]
249
+ }
250
+ });
251
+ ```
252
+
253
+ The adapter will extract:
254
+ - Video source URL
255
+ - Video metadata (title, description)
256
+ - Video dimensions and duration
257
+ - Poster image
258
+ - Frame snapshots (optional)
259
+
260
+ ### Pattern 3: Image Gallery
261
+
262
+ For image-heavy pages:
263
+
264
+ ```javascript
265
+ pbjs.setConfig({
266
+ realTimeData: {
267
+ auctionDelay: 250,
268
+ dataProviders: [{
269
+ name: 'mixpeek',
270
+ waitForIt: true,
271
+ params: {
272
+ apiKey: 'sk_...',
273
+ collectionId: 'col_...',
274
+ mode: 'image',
275
+ maxImages: 10,
276
+ featureExtractors: ['taxonomy', 'image-labels']
277
+ }
278
+ }]
279
+ }
280
+ });
281
+ ```
282
+
283
+ ### Pattern 4: Auto-Detection
284
+
285
+ Let the adapter automatically detect the content type:
286
+
287
+ ```javascript
288
+ pbjs.setConfig({
289
+ realTimeData: {
290
+ auctionDelay: 250,
291
+ dataProviders: [{
292
+ name: 'mixpeek',
293
+ waitForIt: true,
294
+ params: {
295
+ apiKey: 'sk_...',
296
+ collectionId: 'col_...',
297
+ mode: 'auto', // Automatically detects page, video, or image content
298
+ featureExtractors: ['taxonomy', 'brand-safety', 'keywords']
299
+ }
300
+ }]
301
+ }
302
+ });
303
+ ```
304
+
305
+ ## Event Handling
306
+
307
+ Listen to Mixpeek events for debugging and analytics:
308
+
309
+ ```javascript
310
+ pbjs.que.push(function() {
311
+ // Context successfully loaded
312
+ pbjs.onEvent('mixpeekContextReady', function(context) {
313
+ console.log('Context:', context);
314
+
315
+ // Send to analytics
316
+ gtag('event', 'mixpeek_context', {
317
+ taxonomy: context.taxonomy.label,
318
+ score: context.taxonomy.score,
319
+ brand_safety: context.brandSafety
320
+ });
321
+ });
322
+
323
+ // Error occurred
324
+ pbjs.onEvent('mixpeekContextError', function(error) {
325
+ console.error('Mixpeek error:', error);
326
+ });
327
+
328
+ // Cache hit
329
+ pbjs.onEvent('mixpeekContextCached', function(context) {
330
+ console.log('Using cached context');
331
+ });
332
+
333
+ // API request made
334
+ pbjs.onEvent('mixpeekApiRequest', function(data) {
335
+ console.log('API request:', data);
336
+ });
337
+
338
+ // API response received
339
+ pbjs.onEvent('mixpeekApiResponse', function(data) {
340
+ console.log('API response:', data);
341
+ });
342
+ });
343
+ ```
344
+
345
+ ## Targeting Keys
346
+
347
+ The adapter injects the following targeting keys into your ad requests:
348
+
349
+ ### Current Page Context
350
+
351
+ | Key | Description | Example |
352
+ |-----|-------------|---------|
353
+ | `hb_mixpeek_taxonomy` | IAB taxonomy code | `IAB12-6` |
354
+ | `hb_mixpeek_category` | Human-readable category | `Technology > Mobile Phones` |
355
+ | `hb_mixpeek_node` | Taxonomy node ID | `node_mobile_phones` |
356
+ | `hb_mixpeek_path` | Category hierarchy | `tech/mobile/phones` |
357
+ | `hb_mixpeek_score` | Confidence score | `0.92` |
358
+ | `hb_mixpeek_safety` | Brand safety score | `0.98` |
359
+ | `hb_mixpeek_keywords` | Extracted keywords | `mobile,AI,5G` |
360
+ | `hb_mixpeek_sentiment` | Content sentiment | `positive` |
361
+ | `hb_mixpeek_embed` | Embedding ID | `emb_abc123` |
362
+
363
+ ### Previous Ad Context (Adjacency Awareness)
364
+
365
+ | Key | Description | Example |
366
+ |-----|-------------|---------|
367
+ | `hb_mixpeek_prev_creative` | Last creative ID shown | `12345` |
368
+ | `hb_mixpeek_prev_bidder` | Last winning bidder | `appnexus` |
369
+ | `hb_mixpeek_prev_adunit` | Last ad unit code | `sidebar-1` |
370
+ | `hb_mixpeek_prev_cat` | Last ad categories | `IAB18-1,IAB12-3` |
371
+
372
+ These keys are available to all bidders and can be used for:
373
+ - Contextual targeting based on current page content
374
+ - Brand safety filtering
375
+ - Ad adjacency awareness and competitive separation
376
+ - Frequency capping and rotation logic
377
+ - Bid price optimization
378
+ - Reporting and analytics
379
+
380
+ ## Testing
381
+
382
+ ### 1. Test Configuration
383
+
384
+ First, verify your configuration is valid:
385
+
386
+ ```javascript
387
+ // Enable debug mode
388
+ pbjs.setConfig({
389
+ realTimeData: {
390
+ auctionDelay: 250,
391
+ dataProviders: [{
392
+ name: 'mixpeek',
393
+ waitForIt: true,
394
+ params: {
395
+ apiKey: 'sk_...',
396
+ collectionId: 'col_...',
397
+ debug: true // Enable verbose logging
398
+ }
399
+ }]
400
+ }
401
+ });
402
+ ```
403
+
404
+ Open your browser console and look for:
405
+ ```
406
+ [mixpeek] Initializing Mixpeek Context Adapter
407
+ [mixpeek] Configuration { ... }
408
+ [mixpeek] Mixpeek Context Adapter initialized successfully
409
+ ```
410
+
411
+ ### 2. Test Content Extraction
412
+
413
+ Check that content is being extracted properly:
414
+
415
+ ```javascript
416
+ // Access the adapter directly
417
+ const context = await window.MixpeekContextAdapter.getContext();
418
+ console.log('Extracted context:', context);
419
+ ```
420
+
421
+ ### 3. Test API Connection
422
+
423
+ Verify the API is responding:
424
+
425
+ ```javascript
426
+ const health = await window.MixpeekContextAdapter.healthCheck();
427
+ console.log('Health check:', health);
428
+ ```
429
+
430
+ ### 4. Test Targeting Keys
431
+
432
+ Inspect the enriched ad units:
433
+
434
+ ```javascript
435
+ pbjs.onEvent('beforeRequestBids', function(bidRequest) {
436
+ console.log('Ad units:', bidRequest.adUnits);
437
+
438
+ // Check for Mixpeek keys
439
+ const firstUnit = bidRequest.adUnits[0];
440
+ console.log('Targeting keys:', firstUnit.ortb2Imp.ext.data);
441
+ });
442
+ ```
443
+
444
+ ### 5. Test Caching
445
+
446
+ Verify caching is working:
447
+
448
+ ```javascript
449
+ // First request - should hit API
450
+ await window.MixpeekContextAdapter.getContext();
451
+
452
+ // Second request - should use cache
453
+ await window.MixpeekContextAdapter.getContext();
454
+
455
+ // Check cache stats
456
+ const stats = window.MixpeekContextAdapter.getCacheStats();
457
+ console.log('Cache stats:', stats);
458
+ ```
459
+
460
+ ## Deployment
461
+
462
+ ### Production Checklist
463
+
464
+ Before deploying to production:
465
+
466
+ - [ ] Remove `debug: true` from configuration
467
+ - [ ] Set appropriate `timeout` (250ms recommended)
468
+ - [ ] Configure `cacheTTL` based on your content update frequency
469
+ - [ ] Test on multiple page types (articles, videos, galleries)
470
+ - [ ] Verify targeting keys are reaching bidders
471
+ - [ ] Monitor Mixpeek API usage in your dashboard
472
+ - [ ] Set up error monitoring for `mixpeekContextError` events
473
+ - [ ] Configure fallback behavior for API failures
474
+
475
+ ### Environment Variables
476
+
477
+ Store sensitive configuration in environment variables:
478
+
479
+ ```javascript
480
+ pbjs.setConfig({
481
+ mixpeek: {
482
+ apiKey: window.MIXPEEK_API_KEY, // Injected server-side
483
+ collectionId: window.MIXPEEK_COLLECTION_ID,
484
+ namespace: window.MIXPEEK_NAMESPACE
485
+ }
486
+ });
487
+ ```
488
+
489
+ ### Content Security Policy
490
+
491
+ If using CSP, add Mixpeek API to your policy:
492
+
493
+ ```
494
+ connect-src 'self' https://api.mixpeek.com;
495
+ ```
496
+
497
+ ## Troubleshooting
498
+
499
+ ### Adapter Not Initializing
500
+
501
+ **Symptom**: No logs in console, no context enrichment
502
+
503
+ **Solutions**:
504
+ 1. Verify Prebid.js is loaded before the adapter
505
+ 2. Check for JavaScript errors in console
506
+ 3. Ensure configuration is inside `pbjs.que.push()`
507
+
508
+ ```javascript
509
+ // Correct
510
+ pbjs.que.push(function() {
511
+ pbjs.setConfig({ mixpeek: {...} });
512
+ });
513
+
514
+ // Incorrect
515
+ pbjs.setConfig({ mixpeek: {...} }); // Too early
516
+ ```
517
+
518
+ ### API Errors (401 Unauthorized)
519
+
520
+ **Symptom**: `mixpeekContextError` events with 401 status
521
+
522
+ **Solutions**:
523
+ 1. Verify your API key is correct
524
+ 2. Check that the API key hasn't expired
525
+ 3. Ensure the API key has the right permissions
526
+
527
+ ### API Timeout
528
+
529
+ **Symptom**: Requests timing out, no context returned
530
+
531
+ **Solutions**:
532
+ 1. Increase `timeout` value (but keep under 300ms)
533
+ 2. Check your network connection
534
+ 3. Verify Mixpeek API status
535
+
536
+ ### No Content Extracted
537
+
538
+ **Symptom**: Empty context, no classification
539
+
540
+ **Solutions**:
541
+ 1. Check page has sufficient content (min 100 characters)
542
+ 2. Verify the correct `mode` is set
543
+ 3. For video mode, check `videoSelector` matches your video element
544
+ 4. Look for errors in content extractors
545
+
546
+ ### Cache Not Working
547
+
548
+ **Symptom**: Every request hits the API, no cache hits
549
+
550
+ **Solutions**:
551
+ 1. Ensure `enableCache: true`
552
+ 2. Check localStorage is available (not blocked)
553
+ 3. Verify content isn't changing between requests
554
+
555
+ ### Targeting Keys Not Appearing
556
+
557
+ **Symptom**: Ad requests don't include Mixpeek keys
558
+
559
+ **Solutions**:
560
+ 1. Enable `debug: true` and check for errors
561
+ 2. Verify context is loaded before bid requests
562
+ 3. Check the `beforeRequestBids` event is firing
563
+ 4. Inspect `bidRequest.adUnits[0].ortb2Imp.ext.data`
564
+
565
+ ## Support
566
+
567
+ - **Documentation**: [docs.mixpeek.com](https://docs.mixpeek.com)
568
+ - **Email**: support@mixpeek.com
569
+ - **GitHub Issues**: [github.com/mixpeek/prebid-contextual-adapter/issues](https://github.com/mixpeek/prebid-contextual-adapter/issues)
570
+ - **Slack Community**: [Join our Slack](https://mixpeek.com/slack)
571
+
572
+ ## Next Steps
573
+
574
+ - [API Reference](api-reference.md) - Detailed API documentation
575
+ - [Examples](../examples/) - Sample implementations
576
+ - [Migration Guide](migration-guide.md) - Upgrading from older versions
577
+
@@ -0,0 +1,65 @@
1
+ # Mixpeek Prebid Demo
2
+
3
+ This example demonstrates the Mixpeek Context Adapter integrated with Prebid.js.
4
+
5
+ ## Setup
6
+
7
+ 1. Build the adapter:
8
+ ```bash
9
+ cd ../..
10
+ npm install
11
+ npm run build
12
+ ```
13
+
14
+ 2. Update the configuration in `index.html`:
15
+ - Replace `YOUR_MIXPEEK_API_KEY` with your actual API key
16
+ - Replace `YOUR_COLLECTION_ID` with your collection ID
17
+
18
+ 3. Start the demo server:
19
+ ```bash
20
+ npm start
21
+ ```
22
+
23
+ 4. Open http://localhost:8080 in your browser
24
+
25
+ ## Features
26
+
27
+ - Real-time contextual analysis of page content
28
+ - Automatic IAB taxonomy classification
29
+ - Brand safety scoring
30
+ - Keyword extraction
31
+ - Live debug panel showing enrichment data
32
+ - Multiple ad units with contextual targeting
33
+
34
+ ## How It Works
35
+
36
+ 1. The page loads with article content about mobile phones and AI
37
+ 2. Mixpeek Context Adapter extracts the page content
38
+ 3. Content is sent to Mixpeek API for classification
39
+ 4. Taxonomy, brand safety, and keywords are returned
40
+ 5. Targeting keys are injected into Prebid ad requests
41
+ 6. Bidders receive enriched requests with contextual signals
42
+ 7. Ads are served based on contextual relevance
43
+
44
+ ## Configuration
45
+
46
+ See the Mixpeek configuration in `index.html`:
47
+
48
+ ```javascript
49
+ pbjs.setConfig({
50
+ mixpeek: {
51
+ apiKey: 'YOUR_MIXPEEK_API_KEY',
52
+ collectionId: 'YOUR_COLLECTION_ID',
53
+ mode: 'page',
54
+ featureExtractors: ['taxonomy', 'brand-safety', 'keywords'],
55
+ timeout: 250,
56
+ cacheTTL: 300,
57
+ debug: true
58
+ }
59
+ });
60
+ ```
61
+
62
+ ## Testing
63
+
64
+ Try changing the article content and refresh the page to see how the contextual data changes.
65
+