@gravity-ai/api 1.0.2 → 1.1.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 +394 -139
- package/dist/index.d.mts +106 -20
- package/dist/index.d.ts +106 -20
- package/dist/index.js +17 -3
- package/dist/index.mjs +17 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
The official Node.js/TypeScript SDK for the Gravity AI advertising API. Fetch contextually relevant ads based on conversation content.
|
|
4
4
|
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Quick Start](#quick-start)
|
|
9
|
+
- [Migrating from v0](#migrating-from-v0)
|
|
10
|
+
- [Client Configuration](#client-configuration)
|
|
11
|
+
- [Integration Types](#integration-types)
|
|
12
|
+
- [Web](#web)
|
|
13
|
+
- [IDE / CLI](#ide--cli)
|
|
14
|
+
- [Mobile](#mobile)
|
|
15
|
+
- [General](#general)
|
|
16
|
+
- [Response Types](#response-types)
|
|
17
|
+
- [Error Handling](#error-handling)
|
|
18
|
+
- [Using with React](#using-with-react)
|
|
19
|
+
- [Best Practices](#best-practices)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
5
23
|
## Installation
|
|
6
24
|
|
|
7
25
|
```bash
|
|
@@ -10,6 +28,8 @@ npm install @gravity-ai/api
|
|
|
10
28
|
|
|
11
29
|
> **Note:** Requires Node.js 18+
|
|
12
30
|
|
|
31
|
+
---
|
|
32
|
+
|
|
13
33
|
## Quick Start
|
|
14
34
|
|
|
15
35
|
```typescript
|
|
@@ -20,10 +40,14 @@ const client = new Client('your-api-key');
|
|
|
20
40
|
const response = await client.getAd({
|
|
21
41
|
messages: [
|
|
22
42
|
{ role: 'user', content: 'What are some good hiking trails?' },
|
|
23
|
-
{ role: 'assistant', content: 'Here are some popular trails...' }
|
|
24
43
|
],
|
|
25
|
-
sessionId: 'session-123',
|
|
26
|
-
userId: 'user-456',
|
|
44
|
+
sessionId: 'session-123',
|
|
45
|
+
userId: 'user-456',
|
|
46
|
+
numAds: 1,
|
|
47
|
+
render_context: {
|
|
48
|
+
placements: [{ placement: 'below_response' }]
|
|
49
|
+
},
|
|
50
|
+
testAd: true,
|
|
27
51
|
});
|
|
28
52
|
|
|
29
53
|
if (response) {
|
|
@@ -32,142 +56,347 @@ if (response) {
|
|
|
32
56
|
}
|
|
33
57
|
```
|
|
34
58
|
|
|
59
|
+
---
|
|
60
|
+
|
|
35
61
|
## Migrating from v0
|
|
36
62
|
|
|
37
|
-
If you're upgrading from a previous version,
|
|
63
|
+
If you're upgrading from a previous version, there are key changes:
|
|
64
|
+
|
|
65
|
+
**1. `sessionId` is now required**
|
|
66
|
+
|
|
67
|
+
**2. `render_context` object with `placements` array is now required**
|
|
68
|
+
|
|
69
|
+
**3. Response format changed to `ads` array**
|
|
38
70
|
|
|
39
71
|
```typescript
|
|
40
72
|
// Before (v0)
|
|
41
73
|
const ad = await client.getAd({ messages });
|
|
42
|
-
if (ad) {
|
|
43
|
-
console.log(ad.adText);
|
|
44
|
-
}
|
|
45
74
|
|
|
46
75
|
// After (v1)
|
|
47
|
-
const response = await client.getAd({
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
76
|
+
const response = await client.getAd({
|
|
77
|
+
messages,
|
|
78
|
+
sessionId: 'session-123',
|
|
79
|
+
numAds: 1,
|
|
80
|
+
render_context: {
|
|
81
|
+
placements: [{ placement: 'below_response' }]
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
const ad = response?.ads[0];
|
|
52
85
|
```
|
|
53
86
|
|
|
54
|
-
The response is now an object with an `ads` array instead of a single ad object.
|
|
55
|
-
|
|
56
87
|
---
|
|
57
88
|
|
|
58
89
|
## Client Configuration
|
|
59
90
|
|
|
60
|
-
### Basic Initialization
|
|
61
|
-
|
|
62
91
|
```typescript
|
|
63
92
|
import { Client } from '@gravity-ai/api';
|
|
64
93
|
|
|
94
|
+
// Basic
|
|
65
95
|
const client = new Client('your-api-key');
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### Advanced Configuration
|
|
69
|
-
|
|
70
|
-
```typescript
|
|
71
|
-
import { Client } from '@gravity-ai/api';
|
|
72
96
|
|
|
97
|
+
// Advanced
|
|
73
98
|
const client = new Client('your-api-key', {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// Minimum relevancy threshold 0-1 (optional)
|
|
78
|
-
relevancy: 0.8,
|
|
99
|
+
excludedTopics: ['politics', 'religion'], // Global exclusions
|
|
100
|
+
relevancy: 0.6, // Min relevancy threshold (0.1-1)
|
|
79
101
|
});
|
|
80
102
|
```
|
|
81
103
|
|
|
82
|
-
#### Configuration Options
|
|
83
|
-
|
|
84
104
|
| Option | Type | Default | Description |
|
|
85
105
|
|--------|------|---------|-------------|
|
|
86
106
|
| `endpoint` | `string` | `'https://server.trygravity.ai'` | API endpoint URL |
|
|
87
107
|
| `excludedTopics` | `string[]` | `[]` | Topics to exclude from ad matching |
|
|
88
|
-
| `relevancy` | `number
|
|
108
|
+
| `relevancy` | `number` | `null` | Minimum relevancy score (0.1-1) |
|
|
89
109
|
|
|
90
110
|
---
|
|
91
111
|
|
|
92
|
-
##
|
|
112
|
+
## Integration Types
|
|
113
|
+
|
|
114
|
+
Choose the integration type that matches your application. All types share a **common schema**.
|
|
115
|
+
|
|
116
|
+
### Common Fields
|
|
117
|
+
|
|
118
|
+
| Field | Type | Description |
|
|
119
|
+
|-------|------|-------------|
|
|
120
|
+
| `messages` | `MessageObject[]` | Conversation context. Array of `{role, content}` objects. **Required.** |
|
|
121
|
+
| `sessionId` | `string` | Session identifier for frequency capping. **Required.** |
|
|
122
|
+
| `render_context` | `RenderContextObject` | Describes how the ad will be rendered in your app. **Required.** |
|
|
123
|
+
| `userId` | `string` | Unique user identifier. |
|
|
124
|
+
| `testAd` | `boolean` | Returns real ad without tracking. Use for testing. |
|
|
125
|
+
| `numAds` | `number` | Number of ads to return (1-3). Must match `placements` length. |
|
|
126
|
+
|
|
127
|
+
#### What is `render_context`?
|
|
128
|
+
|
|
129
|
+
The `render_context` object describes how the ad will be rendered in your app, so Gravity can generate a more contextually relevant ad.
|
|
130
|
+
|
|
131
|
+
For example:
|
|
132
|
+
- **`placements`** — Where you plan to show the ad (below the response, in a sidebar, etc.)
|
|
133
|
+
- **`max_ad_length`** — Character limit you can display, so we don't send copy that gets truncated
|
|
134
|
+
- **`supports_markdown`** — Whether you can render formatted text
|
|
135
|
+
- **`supports_images`** — Whether you can display brand logos or product images
|
|
136
|
+
|
|
137
|
+
The more context you provide, the better we can optimize the ad copy, format, and creative for your specific integration.
|
|
138
|
+
|
|
139
|
+
<details>
|
|
140
|
+
<summary><strong>RenderContextObject</strong></summary>
|
|
141
|
+
|
|
142
|
+
| Field | Type | Description |
|
|
143
|
+
|-------|------|-------------|
|
|
144
|
+
| `placements` | `PlacementObject[]` | Array of placement objects (1-3). Length must match `numAds`. **Required.** |
|
|
145
|
+
| `max_ad_length` | `number` | Max characters for ad text. |
|
|
146
|
+
| `supports_markdown` | `boolean` | Whether markdown rendering is supported. |
|
|
147
|
+
| `supports_links` | `boolean` | Whether clickable links are supported. |
|
|
148
|
+
| `supports_images` | `boolean` | Whether images can be displayed. |
|
|
149
|
+
| `supports_cta_button` | `boolean` | Whether CTA buttons are supported. |
|
|
150
|
+
|
|
151
|
+
</details>
|
|
152
|
+
|
|
153
|
+
<details>
|
|
154
|
+
<summary><strong>PlacementObject</strong></summary>
|
|
93
155
|
|
|
94
|
-
|
|
156
|
+
| Field | Type | Description |
|
|
157
|
+
|-------|------|-------------|
|
|
158
|
+
| `placement` | `string` | **Required.** One of: `"above_response"`, `"below_response"`, `"inline_response"`, `"left_response"`, `"right_response"` |
|
|
159
|
+
| `placement_id` | `string` | Optional tracking ID for this ad slot. |
|
|
160
|
+
|
|
161
|
+
</details>
|
|
162
|
+
|
|
163
|
+
<details>
|
|
164
|
+
<summary><strong>DeviceObject</strong></summary>
|
|
165
|
+
|
|
166
|
+
| Field | Type | Description |
|
|
167
|
+
|-------|------|-------------|
|
|
168
|
+
| `ip` | `string` | IP address for geo-targeting. **Required.** |
|
|
169
|
+
| `ua` | `string` | User agent string. Enables browser/device detection. |
|
|
170
|
+
| `os` | `string` | Operating system: `"macos"`, `"windows"`, `"linux"`, `"iOS"`, `"Android"`. |
|
|
171
|
+
| `os_version` | `string` | OS version (e.g., `"17.2"`). |
|
|
172
|
+
| `browser` | `string` | Browser name: `"chrome"`, `"safari"`, `"firefox"`. |
|
|
173
|
+
| `device_type` | `string` | `"desktop"`, `"mobile"`, `"tablet"`. |
|
|
174
|
+
| `device_model` | `string` | Device model (e.g., `"iPhone 15 Pro"`). |
|
|
175
|
+
| `ifa` | `string` | IDFA/GAID for cross-app attribution. **Higher CPMs.** |
|
|
176
|
+
| `timezone` | `string` | IANA timezone (e.g., `"America/New_York"`). |
|
|
177
|
+
| `locale` | `string` | Locale (e.g., `"en-US"`). |
|
|
178
|
+
| `connection_type` | `string` | `"wifi"` or `"cellular"`. |
|
|
179
|
+
|
|
180
|
+
</details>
|
|
181
|
+
|
|
182
|
+
<details>
|
|
183
|
+
<summary><strong>UserObject</strong></summary>
|
|
184
|
+
|
|
185
|
+
| Field | Type | Description |
|
|
186
|
+
|-------|------|-------------|
|
|
187
|
+
| `email` | `string` | User's email for identity matching. **Higher CPMs.** |
|
|
188
|
+
| `gender` | `string` | `"male"`, `"female"`, `"other"`. |
|
|
189
|
+
| `age` | `string` | Age range: `"18-24"`, `"25-34"`, `"35-44"`, etc. |
|
|
190
|
+
| `keywords` | `string` | Comma-separated interest keywords. |
|
|
191
|
+
| `subscription_tier` | `string` | `"free"`, `"pro"`, `"premium"`, `"enterprise"`. |
|
|
192
|
+
| `user_created_at` | `string` | Account creation date (ISO 8601). |
|
|
193
|
+
| `user_interests` | `string[]` | Array of user interests for targeting. |
|
|
194
|
+
|
|
195
|
+
</details>
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
### Web
|
|
200
|
+
|
|
201
|
+
**For:** Chat interfaces, AI assistants, web apps with conversational UI
|
|
202
|
+
|
|
203
|
+
#### Web-specific Fields
|
|
204
|
+
|
|
205
|
+
| Field | Type | Description |
|
|
206
|
+
|-------|------|-------------|
|
|
207
|
+
| `web.referrer` | `string` | Referring URL. Enables traffic source targeting. |
|
|
208
|
+
|
|
209
|
+
#### Example
|
|
95
210
|
|
|
96
211
|
```typescript
|
|
97
212
|
const response = await client.getAd({
|
|
213
|
+
// Common fields
|
|
98
214
|
messages: [
|
|
99
|
-
{ role: 'user', content: '
|
|
100
|
-
{ role: 'assistant', content: 'What is your budget?' }
|
|
215
|
+
{ role: 'user', content: 'What are the best practices for React performance?' }
|
|
101
216
|
],
|
|
102
|
-
sessionId: 'session-
|
|
103
|
-
userId: 'user-
|
|
104
|
-
numAds: 1,
|
|
217
|
+
sessionId: 'session-web-001',
|
|
218
|
+
userId: 'user-web-789',
|
|
219
|
+
numAds: 1,
|
|
220
|
+
testAd: true,
|
|
221
|
+
render_context: {
|
|
222
|
+
placements: [
|
|
223
|
+
{ placement: 'right_response', placement_id: 'sidebar-1' }
|
|
224
|
+
],
|
|
225
|
+
max_ad_length: 200
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// Web-specific fields
|
|
229
|
+
user: {
|
|
230
|
+
email: 'webuser@example.com',
|
|
231
|
+
subscription_tier: 'pro'
|
|
232
|
+
},
|
|
233
|
+
device: {
|
|
234
|
+
ip: '203.0.113.50',
|
|
235
|
+
ua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0',
|
|
236
|
+
browser: 'chrome',
|
|
237
|
+
device_type: 'desktop',
|
|
238
|
+
timezone: 'Europe/London',
|
|
239
|
+
locale: 'en-GB'
|
|
240
|
+
},
|
|
241
|
+
web: {
|
|
242
|
+
referrer: 'https://google.com'
|
|
243
|
+
}
|
|
105
244
|
});
|
|
245
|
+
```
|
|
106
246
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### IDE / CLI
|
|
250
|
+
|
|
251
|
+
**For:** Dev tools like Cursor, Claude Code, GitHub Copilot, Windsurf and VS Code extensions
|
|
252
|
+
|
|
253
|
+
#### IDE-specific Fields
|
|
254
|
+
|
|
255
|
+
<details>
|
|
256
|
+
<summary><strong>IDEObject</strong></summary>
|
|
257
|
+
|
|
258
|
+
| Field | Type | Description |
|
|
259
|
+
|-------|------|-------------|
|
|
260
|
+
| `name` | `string` | IDE name: `"cursor"`, `"vscode"`, `"intellij"`. |
|
|
261
|
+
| `session_duration_ms` | `number` | Time since IDE opened. Helps with engagement-based targeting. |
|
|
262
|
+
| `active_file_language` | `string` | Current file language (e.g., `"typescript"`). |
|
|
263
|
+
|
|
264
|
+
</details>
|
|
265
|
+
|
|
266
|
+
#### Example
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
const response = await client.getAd({
|
|
270
|
+
// Common fields
|
|
271
|
+
messages: [
|
|
272
|
+
{ role: 'user', content: 'How do I set up authentication in my Express app?' }
|
|
273
|
+
],
|
|
274
|
+
sessionId: 'session-ide-001',
|
|
275
|
+
userId: 'user-dev-123',
|
|
276
|
+
numAds: 1,
|
|
277
|
+
testAd: true,
|
|
278
|
+
render_context: {
|
|
279
|
+
placements: [
|
|
280
|
+
{ placement: 'below_response' }
|
|
281
|
+
],
|
|
282
|
+
max_ad_length: 280,
|
|
283
|
+
supports_markdown: true,
|
|
284
|
+
supports_links: true
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
// IDE-specific fields
|
|
288
|
+
user: {
|
|
289
|
+
email: 'developer@example.com'
|
|
290
|
+
},
|
|
291
|
+
device: {
|
|
292
|
+
ip: '192.168.1.100',
|
|
293
|
+
os: 'macos',
|
|
294
|
+
timezone: 'America/New_York',
|
|
295
|
+
locale: 'en-US'
|
|
296
|
+
},
|
|
297
|
+
ide: {
|
|
298
|
+
name: 'cursor',
|
|
299
|
+
session_duration_ms: 3600000,
|
|
300
|
+
active_file_language: 'typescript'
|
|
301
|
+
}
|
|
302
|
+
});
|
|
111
303
|
```
|
|
112
304
|
|
|
113
|
-
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
### Mobile
|
|
308
|
+
|
|
309
|
+
**For:** iOS apps, Android apps, React Native, Flutter
|
|
310
|
+
|
|
311
|
+
#### Mobile-specific Fields
|
|
312
|
+
|
|
313
|
+
<details>
|
|
314
|
+
<summary><strong>AppObject</strong></summary>
|
|
315
|
+
|
|
316
|
+
| Field | Type | Description |
|
|
317
|
+
|-------|------|-------------|
|
|
318
|
+
| `version` | `string` | Your app version. |
|
|
319
|
+
|
|
320
|
+
</details>
|
|
321
|
+
|
|
322
|
+
#### Example
|
|
114
323
|
|
|
115
324
|
```typescript
|
|
116
325
|
const response = await client.getAd({
|
|
117
|
-
//
|
|
326
|
+
// Common fields
|
|
118
327
|
messages: [
|
|
119
|
-
{ role: '
|
|
120
|
-
{ role: '
|
|
328
|
+
{ role: 'assistant', content: 'I found several Italian restaurants nearby.' },
|
|
329
|
+
{ role: 'user', content: 'Which one has the best pasta?' }
|
|
121
330
|
],
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
331
|
+
sessionId: 'session-mobile-001',
|
|
332
|
+
userId: 'user-app-456',
|
|
333
|
+
numAds: 1,
|
|
334
|
+
testAd: true,
|
|
335
|
+
render_context: {
|
|
336
|
+
placements: [
|
|
337
|
+
{ placement: 'inline_response' }
|
|
338
|
+
],
|
|
339
|
+
max_ad_length: 150,
|
|
340
|
+
supports_images: true,
|
|
341
|
+
supports_cta_button: true
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
// Mobile-specific fields
|
|
128
345
|
user: {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
346
|
+
email: 'user@example.com',
|
|
347
|
+
subscription_tier: 'premium',
|
|
348
|
+
user_created_at: '2023-06-15T00:00:00Z',
|
|
349
|
+
user_interests: ['food', 'dining', 'travel']
|
|
133
350
|
},
|
|
134
|
-
|
|
135
|
-
// Optional: device information
|
|
136
351
|
device: {
|
|
137
|
-
ip: '
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
352
|
+
ip: '198.51.100.23',
|
|
353
|
+
ua: 'MyApp/2.1.0 (iPhone; iOS 17.2)',
|
|
354
|
+
os: 'iOS',
|
|
355
|
+
os_version: '17.2',
|
|
356
|
+
device_model: 'iPhone 15 Pro',
|
|
357
|
+
ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC',
|
|
358
|
+
timezone: 'America/Los_Angeles',
|
|
359
|
+
locale: 'en-US',
|
|
360
|
+
connection_type: 'wifi'
|
|
142
361
|
},
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
relevancy: 0.8, // Min relevancy threshold (0-1)
|
|
147
|
-
numAds: 1, // Number of ads (1-3)
|
|
148
|
-
testAd: false, // Return test ad when true
|
|
149
|
-
|
|
150
|
-
// Optional: custom fields (open-ended, passed to matching)
|
|
151
|
-
interests: ['coding', 'apple', 'software development'],
|
|
152
|
-
summary: 'User wants a laptop for software development',
|
|
362
|
+
app: {
|
|
363
|
+
version: '2.1.0'
|
|
364
|
+
}
|
|
153
365
|
});
|
|
154
366
|
```
|
|
155
367
|
|
|
156
368
|
---
|
|
157
369
|
|
|
158
|
-
|
|
370
|
+
### General
|
|
371
|
+
|
|
372
|
+
**For:** Any integration not covered above.
|
|
373
|
+
|
|
374
|
+
#### Example
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
const response = await client.getAd({
|
|
378
|
+
// Common fields
|
|
379
|
+
messages: [
|
|
380
|
+
{ role: 'user', content: 'Where can I buy marathon gear?' }
|
|
381
|
+
],
|
|
382
|
+
sessionId: 'session-general-001',
|
|
383
|
+
userId: 'user-general-123',
|
|
384
|
+
numAds: 1,
|
|
385
|
+
testAd: true,
|
|
386
|
+
render_context: {
|
|
387
|
+
placements: [
|
|
388
|
+
{ placement: 'below_response' }
|
|
389
|
+
]
|
|
390
|
+
},
|
|
159
391
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
| `relevancy` | `number` | - | Min relevancy (0-1) |
|
|
169
|
-
| `numAds` | `number` | - | Number of ads (1-3, default 1) |
|
|
170
|
-
| `testAd` | `boolean` | - | Return test ad when true |
|
|
392
|
+
// Optional fields
|
|
393
|
+
device: {
|
|
394
|
+
ip: '192.168.1.1',
|
|
395
|
+
timezone: 'America/New_York',
|
|
396
|
+
locale: 'en-US'
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
```
|
|
171
400
|
|
|
172
401
|
---
|
|
173
402
|
|
|
@@ -175,15 +404,17 @@ const response = await client.getAd({
|
|
|
175
404
|
|
|
176
405
|
### AdResponse
|
|
177
406
|
|
|
178
|
-
Returned by `getAd()`.
|
|
179
|
-
|
|
180
407
|
```typescript
|
|
181
408
|
interface AdResponse {
|
|
182
|
-
ads: Ad[];
|
|
409
|
+
ads: Ad[]; // Array of ads (one per placement)
|
|
183
410
|
numAds: number; // Number of ads returned
|
|
184
411
|
totalPayout?: number; // Total payout across all ads
|
|
185
412
|
}
|
|
413
|
+
```
|
|
186
414
|
|
|
415
|
+
### Ad
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
187
418
|
interface Ad {
|
|
188
419
|
adText: string; // Ad copy text
|
|
189
420
|
adId: string; // Unique ad identifier
|
|
@@ -192,45 +423,32 @@ interface Ad {
|
|
|
192
423
|
brandImage?: string; // Brand logo URL
|
|
193
424
|
url?: string; // Landing page URL
|
|
194
425
|
favicon?: string; // Favicon URL
|
|
195
|
-
impUrl?: string; // Impression tracking URL
|
|
196
|
-
clickUrl?: string; // Click-through URL
|
|
197
|
-
payout?: number; // Payout amount
|
|
426
|
+
impUrl?: string; // Impression tracking URL (null for testAd)
|
|
427
|
+
clickUrl?: string; // Click-through URL (null for testAd)
|
|
428
|
+
payout?: number; // Payout amount (null for testAd)
|
|
198
429
|
}
|
|
199
430
|
```
|
|
200
431
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
## Common Types
|
|
204
|
-
|
|
205
|
-
### Message Object
|
|
432
|
+
### Request Types
|
|
206
433
|
|
|
207
434
|
```typescript
|
|
208
435
|
interface MessageObject {
|
|
209
436
|
role: 'user' | 'assistant';
|
|
210
437
|
content: string;
|
|
211
438
|
}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
### User Object
|
|
215
439
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
440
|
+
interface RenderContextObject {
|
|
441
|
+
placements: PlacementObject[]; // Required, 1-3 items
|
|
442
|
+
max_ad_length?: number;
|
|
443
|
+
supports_markdown?: boolean;
|
|
444
|
+
supports_links?: boolean;
|
|
445
|
+
supports_images?: boolean;
|
|
446
|
+
supports_cta_button?: boolean;
|
|
222
447
|
}
|
|
223
|
-
```
|
|
224
|
-
|
|
225
|
-
### Device Object
|
|
226
448
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
country: string; // ISO country code
|
|
231
|
-
ua: string; // User agent
|
|
232
|
-
os?: string; // Operating system
|
|
233
|
-
ifa?: string; // Advertising ID
|
|
449
|
+
interface PlacementObject {
|
|
450
|
+
placement: 'above_response' | 'below_response' | 'inline_response' | 'left_response' | 'right_response';
|
|
451
|
+
placement_id?: string;
|
|
234
452
|
}
|
|
235
453
|
```
|
|
236
454
|
|
|
@@ -238,41 +456,41 @@ interface DeviceObject {
|
|
|
238
456
|
|
|
239
457
|
## Error Handling
|
|
240
458
|
|
|
241
|
-
The client
|
|
459
|
+
The client returns `null` on failure. Errors are logged to console.
|
|
242
460
|
|
|
243
461
|
```typescript
|
|
244
|
-
const response = await client.getAd({
|
|
462
|
+
const response = await client.getAd({
|
|
463
|
+
messages,
|
|
464
|
+
sessionId: 'session-123',
|
|
465
|
+
numAds: 1,
|
|
466
|
+
render_context: { placements: [{ placement: 'below_response' }] }
|
|
467
|
+
});
|
|
245
468
|
|
|
246
469
|
// Returns null on:
|
|
247
470
|
// - Network errors
|
|
248
|
-
// -
|
|
249
|
-
// -
|
|
250
|
-
// -
|
|
471
|
+
// - 401: Invalid API key
|
|
472
|
+
// - 422: Validation error (missing sessionId, render_context, or numAds/placements mismatch)
|
|
473
|
+
// - 204: No relevant ad found
|
|
474
|
+
// - 429: Rate limit exceeded
|
|
251
475
|
|
|
252
476
|
if (!response) {
|
|
253
477
|
// Handle gracefully - don't break the user experience
|
|
254
478
|
}
|
|
255
479
|
```
|
|
256
480
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
481
|
+
| Status | Meaning |
|
|
482
|
+
|--------|---------|
|
|
483
|
+
| `200` | Ad(s) matched and returned successfully |
|
|
484
|
+
| `204` | No matching ads found (null response) |
|
|
485
|
+
| `401` | Invalid or missing API key |
|
|
486
|
+
| `422` | Validation error (e.g., missing `sessionId`, `render_context`, or `numAds`/`placements` mismatch) |
|
|
487
|
+
| `429` | Rate limit exceeded |
|
|
260
488
|
|
|
261
|
-
|
|
262
|
-
import { Client, ClientParams } from '@gravity-ai/api';
|
|
263
|
-
import type {
|
|
264
|
-
AdParams,
|
|
265
|
-
Ad,
|
|
266
|
-
AdResponse,
|
|
267
|
-
MessageObject,
|
|
268
|
-
DeviceObject,
|
|
269
|
-
UserObject,
|
|
270
|
-
} from '@gravity-ai/api';
|
|
271
|
-
```
|
|
489
|
+
---
|
|
272
490
|
|
|
273
491
|
## Using with React
|
|
274
492
|
|
|
275
|
-
For React applications,
|
|
493
|
+
For React applications, use the companion package `@gravity-ai/react`:
|
|
276
494
|
|
|
277
495
|
```bash
|
|
278
496
|
npm install @gravity-ai/api @gravity-ai/react
|
|
@@ -286,12 +504,15 @@ const client = new Client('your-api-key');
|
|
|
286
504
|
|
|
287
505
|
function ChatApp() {
|
|
288
506
|
const [ad, setAd] = useState(null);
|
|
289
|
-
|
|
507
|
+
|
|
290
508
|
useEffect(() => {
|
|
291
|
-
client.getAd({
|
|
509
|
+
client.getAd({
|
|
292
510
|
messages,
|
|
293
511
|
sessionId: 'session-123',
|
|
294
512
|
userId: 'user-456',
|
|
513
|
+
numAds: 1,
|
|
514
|
+
render_context: { placements: [{ placement: 'below_response' }] },
|
|
515
|
+
testAd: true,
|
|
295
516
|
}).then(res => setAd(res?.ads[0] || null));
|
|
296
517
|
}, [messages]);
|
|
297
518
|
|
|
@@ -299,13 +520,47 @@ function ChatApp() {
|
|
|
299
520
|
}
|
|
300
521
|
```
|
|
301
522
|
|
|
523
|
+
---
|
|
524
|
+
|
|
302
525
|
## Best Practices
|
|
303
526
|
|
|
304
|
-
1.
|
|
527
|
+
1. **`sessionId` and `render_context` are required** — Enable frequency capping and ad placement tracking.
|
|
528
|
+
|
|
529
|
+
2. **`numAds` must match `placements` length** — Request 2 ads? Provide 2 placement objects.
|
|
530
|
+
|
|
531
|
+
3. **Include `userId` when available** — Improves targeting and increases CPMs.
|
|
305
532
|
|
|
306
|
-
|
|
533
|
+
4. **Use `testAd: true` during development** — Prevents generating real impressions or clicks.
|
|
307
534
|
|
|
308
|
-
|
|
535
|
+
5. **Handle null responses gracefully** — Don't break the UX when no ad is available.
|
|
536
|
+
|
|
537
|
+
6. **Fire `impUrl` when the ad is visible** — Required for proper impression tracking.
|
|
538
|
+
|
|
539
|
+
7. **Include `device.ip` for geo-targeting** — Enables location-based ads and higher CPMs.
|
|
540
|
+
|
|
541
|
+
8. **Include `user.email` when available** — Enables identity matching for significantly higher CPMs.
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## TypeScript
|
|
546
|
+
|
|
547
|
+
Full TypeScript support with exported types:
|
|
548
|
+
|
|
549
|
+
```typescript
|
|
550
|
+
import { Client } from '@gravity-ai/api';
|
|
551
|
+
import type {
|
|
552
|
+
AdParams,
|
|
553
|
+
Ad,
|
|
554
|
+
AdResponse,
|
|
555
|
+
MessageObject,
|
|
556
|
+
RenderContextObject,
|
|
557
|
+
PlacementObject,
|
|
558
|
+
DeviceObject,
|
|
559
|
+
UserObject,
|
|
560
|
+
} from '@gravity-ai/api';
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
---
|
|
309
564
|
|
|
310
565
|
## License
|
|
311
566
|
|
package/dist/index.d.mts
CHANGED
|
@@ -8,6 +8,58 @@ type Role = 'user' | 'assistant';
|
|
|
8
8
|
* @description Used for demographic targeting of advertisements
|
|
9
9
|
*/
|
|
10
10
|
type Gender = 'male' | 'female' | 'other';
|
|
11
|
+
/**
|
|
12
|
+
* Placement positions for ad rendering
|
|
13
|
+
* @description Specifies where ads should appear relative to the AI response
|
|
14
|
+
*/
|
|
15
|
+
type Placement = 'above_response' | 'below_response' | 'inline_response' | 'left_response' | 'right_response';
|
|
16
|
+
/**
|
|
17
|
+
* Individual ad placement specification
|
|
18
|
+
* @description Defines a single ad slot with its position and optional tracking ID
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const placement: PlacementObject = {
|
|
22
|
+
* placement: 'below_response',
|
|
23
|
+
* placement_id: 'sidebar-1'
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
interface PlacementObject {
|
|
28
|
+
/** Position where the ad should appear (required) */
|
|
29
|
+
placement: Placement;
|
|
30
|
+
/** Optional tracking ID for this specific ad slot */
|
|
31
|
+
placement_id?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Describes how your app will display the ad
|
|
35
|
+
* @description Contains placement array and rendering capabilities for ad customization
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const renderContext: RenderContextObject = {
|
|
39
|
+
* placements: [
|
|
40
|
+
* { placement: 'below_response' },
|
|
41
|
+
* { placement: 'right_response', placement_id: 'sidebar' }
|
|
42
|
+
* ],
|
|
43
|
+
* max_ad_length: 200
|
|
44
|
+
* };
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
interface RenderContextObject {
|
|
48
|
+
/** Where you plan to show the ad(s). Array of 1-3 placements, must match numAds. */
|
|
49
|
+
placements: PlacementObject[];
|
|
50
|
+
/** Character limit you can display, so we don't send copy that gets truncated */
|
|
51
|
+
max_ad_length?: number;
|
|
52
|
+
/** Whether you can render markdown-formatted text */
|
|
53
|
+
supports_markdown?: boolean;
|
|
54
|
+
/** Whether you can render clickable links */
|
|
55
|
+
supports_links?: boolean;
|
|
56
|
+
/** Whether you can display images (brand logos, product images) */
|
|
57
|
+
supports_images?: boolean;
|
|
58
|
+
/** Whether you can render CTA buttons */
|
|
59
|
+
supports_cta_button?: boolean;
|
|
60
|
+
/** Additional render context properties (supports JSON objects) */
|
|
61
|
+
[key: string]: PlacementObject[] | string | number | boolean | object | null | undefined;
|
|
62
|
+
}
|
|
11
63
|
/**
|
|
12
64
|
* Represents a single message in a conversation
|
|
13
65
|
* @description Used to provide conversation context for contextual ad targeting
|
|
@@ -39,16 +91,18 @@ interface MessageObject {
|
|
|
39
91
|
* ```
|
|
40
92
|
*/
|
|
41
93
|
interface DeviceObject {
|
|
42
|
-
/** User's IP address for geo-targeting */
|
|
94
|
+
/** User's IP address for geo-targeting (required) */
|
|
43
95
|
ip: string;
|
|
96
|
+
/** Browser user-agent string (optional for non-web publishers like IDEs, CLIs, mobile apps) */
|
|
97
|
+
ua?: string;
|
|
44
98
|
/** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
|
|
45
|
-
country
|
|
46
|
-
/** User agent string from the browser */
|
|
47
|
-
ua: string;
|
|
99
|
+
country?: string;
|
|
48
100
|
/** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
|
|
49
101
|
os?: string;
|
|
50
102
|
/** Identifier for Advertisers (mobile advertising ID) */
|
|
51
103
|
ifa?: string;
|
|
104
|
+
/** Additional device properties (timezone, locale, browser, device_type, screen dimensions, etc.) */
|
|
105
|
+
[key: string]: string | number | boolean | undefined;
|
|
52
106
|
}
|
|
53
107
|
/**
|
|
54
108
|
* User profile information for ad targeting
|
|
@@ -64,7 +118,7 @@ interface DeviceObject {
|
|
|
64
118
|
* ```
|
|
65
119
|
*/
|
|
66
120
|
interface UserObject {
|
|
67
|
-
/** Unique user identifier for
|
|
121
|
+
/** Unique user identifier for improving ad relevance */
|
|
68
122
|
uid?: string;
|
|
69
123
|
/** User's gender for demographic targeting */
|
|
70
124
|
gender?: Gender;
|
|
@@ -72,6 +126,8 @@ interface UserObject {
|
|
|
72
126
|
age?: string;
|
|
73
127
|
/** Comma-separated keywords representing user interests */
|
|
74
128
|
keywords?: string;
|
|
129
|
+
/** Additional user properties (email, subscription_tier, user_interests, company_size, etc.) */
|
|
130
|
+
[key: string]: string | string[] | number | boolean | Gender | undefined;
|
|
75
131
|
}
|
|
76
132
|
/**
|
|
77
133
|
* Parameters for requesting an advertisement
|
|
@@ -84,7 +140,12 @@ interface UserObject {
|
|
|
84
140
|
* { role: 'assistant', content: 'What is your budget?' }
|
|
85
141
|
* ],
|
|
86
142
|
* sessionId: 'session-123',
|
|
143
|
+
* numAds: 1,
|
|
144
|
+
* render_context: {
|
|
145
|
+
* placements: [{ placement: 'below_response' }]
|
|
146
|
+
* },
|
|
87
147
|
* userId: 'user-456',
|
|
148
|
+
* testAd: true,
|
|
88
149
|
* user: { gender: 'male', age: '25-34' },
|
|
89
150
|
* device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
|
|
90
151
|
* excludedTopics: ['politics'],
|
|
@@ -95,8 +156,12 @@ interface UserObject {
|
|
|
95
156
|
interface AdParams {
|
|
96
157
|
/** Array of conversation messages for contextual targeting (required) */
|
|
97
158
|
messages: MessageObject[];
|
|
98
|
-
/** Session identifier for
|
|
99
|
-
sessionId
|
|
159
|
+
/** Session identifier for ad relevance (required) */
|
|
160
|
+
sessionId: string;
|
|
161
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
162
|
+
render_context: RenderContextObject;
|
|
163
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
164
|
+
numAds?: number;
|
|
100
165
|
/** Unique user identifier */
|
|
101
166
|
userId?: string;
|
|
102
167
|
/** Device and location information */
|
|
@@ -107,8 +172,6 @@ interface AdParams {
|
|
|
107
172
|
excludedTopics?: string[];
|
|
108
173
|
/** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
|
|
109
174
|
relevancy?: number | null;
|
|
110
|
-
/** Number of ads to return (1-3, default 1) */
|
|
111
|
-
numAds?: number;
|
|
112
175
|
/** Returns a test ad when true */
|
|
113
176
|
testAd?: boolean;
|
|
114
177
|
/**
|
|
@@ -185,8 +248,12 @@ interface ApiErrorResponse {
|
|
|
185
248
|
* Base fields shared across all ad requests.
|
|
186
249
|
*/
|
|
187
250
|
interface AdRequestBase {
|
|
188
|
-
/** Session identifier for
|
|
189
|
-
sessionId
|
|
251
|
+
/** Session identifier for ad relevance (required) */
|
|
252
|
+
sessionId: string;
|
|
253
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
254
|
+
render_context: RenderContextObject;
|
|
255
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
256
|
+
numAds?: number;
|
|
190
257
|
/** Unique user identifier */
|
|
191
258
|
userId?: string;
|
|
192
259
|
/** Device and location information */
|
|
@@ -197,8 +264,6 @@ interface AdRequestBase {
|
|
|
197
264
|
excludedTopics?: string[];
|
|
198
265
|
/** Minimum relevancy score threshold (0-1) */
|
|
199
266
|
relevancy?: number | null;
|
|
200
|
-
/** Number of ads to return (1-3, default 1) */
|
|
201
|
-
numAds?: number;
|
|
202
267
|
/** Returns a test ad when true */
|
|
203
268
|
testAd?: boolean;
|
|
204
269
|
/** Additional custom fields */
|
|
@@ -221,13 +286,16 @@ interface NonContextualAdParams extends AdRequestBase {
|
|
|
221
286
|
/**
|
|
222
287
|
* POST /api/v1/bid
|
|
223
288
|
* @description Two-phase bid request. Returns bid price and bidId.
|
|
224
|
-
* @note Does NOT extend AdRequestBaseV1 - has its own field set.
|
|
225
289
|
*/
|
|
226
290
|
interface BidParams {
|
|
227
291
|
/** Array of conversation messages (required) */
|
|
228
292
|
messages: MessageObject[];
|
|
229
|
-
/** Session identifier */
|
|
230
|
-
sessionId
|
|
293
|
+
/** Session identifier for ad relevance (required) */
|
|
294
|
+
sessionId: string;
|
|
295
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
296
|
+
render_context: RenderContextObject;
|
|
297
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
298
|
+
numAds?: number;
|
|
231
299
|
/** Unique user identifier */
|
|
232
300
|
userId?: string;
|
|
233
301
|
/** Chat/conversation identifier */
|
|
@@ -304,6 +372,10 @@ interface ClientParams {
|
|
|
304
372
|
* { role: 'user', content: 'What laptop should I buy?' }
|
|
305
373
|
* ],
|
|
306
374
|
* sessionId: 'session-123',
|
|
375
|
+
* numAds: 1,
|
|
376
|
+
* render_context: {
|
|
377
|
+
* placements: [{ placement: 'below_response' }]
|
|
378
|
+
* }
|
|
307
379
|
* });
|
|
308
380
|
*
|
|
309
381
|
* if (response) {
|
|
@@ -370,6 +442,10 @@ declare class Client {
|
|
|
370
442
|
* { role: 'assistant', content: 'What is your budget range?' }
|
|
371
443
|
* ],
|
|
372
444
|
* sessionId: 'session-123',
|
|
445
|
+
* numAds: 1,
|
|
446
|
+
* render_context: {
|
|
447
|
+
* placements: [{ placement: 'below_response' }]
|
|
448
|
+
* },
|
|
373
449
|
* userId: 'user-456',
|
|
374
450
|
* });
|
|
375
451
|
*
|
|
@@ -384,6 +460,11 @@ declare class Client {
|
|
|
384
460
|
* const response = await client.getAd({
|
|
385
461
|
* messages: [...],
|
|
386
462
|
* sessionId: 'session-123',
|
|
463
|
+
* numAds: 1,
|
|
464
|
+
* render_context: {
|
|
465
|
+
* placements: [{ placement: 'below_response' }],
|
|
466
|
+
* max_ad_length: 200
|
|
467
|
+
* },
|
|
387
468
|
* userId: 'user-456',
|
|
388
469
|
* user: {
|
|
389
470
|
* uid: 'user-123',
|
|
@@ -402,7 +483,12 @@ declare class Client {
|
|
|
402
483
|
*
|
|
403
484
|
* @example Handling the response
|
|
404
485
|
* ```typescript
|
|
405
|
-
* const response = await client.getAd({
|
|
486
|
+
* const response = await client.getAd({
|
|
487
|
+
* messages,
|
|
488
|
+
* sessionId: '...',
|
|
489
|
+
* numAds: 1,
|
|
490
|
+
* render_context: { placements: [{ placement: 'below_response' }] }
|
|
491
|
+
* });
|
|
406
492
|
*
|
|
407
493
|
* if (response) {
|
|
408
494
|
* const ad = response.ads[0];
|
|
@@ -433,10 +519,10 @@ declare class Client {
|
|
|
433
519
|
* @description Fetches ads without context matching. Useful for brand awareness placements.
|
|
434
520
|
* Returns null if no ad is available or on error.
|
|
435
521
|
*
|
|
436
|
-
* @param params -
|
|
522
|
+
* @param params - Request parameters (sessionId required)
|
|
437
523
|
* @returns Promise resolving to AdResponse or null if no ad available
|
|
438
524
|
*/
|
|
439
|
-
nonContextualAd(params
|
|
525
|
+
nonContextualAd(params: NonContextualAdParams): Promise<AdResponse | null>;
|
|
440
526
|
/**
|
|
441
527
|
* Request a bid price for contextual ad placement
|
|
442
528
|
*
|
|
@@ -472,4 +558,4 @@ declare class Client {
|
|
|
472
558
|
private handleError;
|
|
473
559
|
}
|
|
474
560
|
|
|
475
|
-
export { type Ad, type AdParams, type AdRequestBase, type AdResponse, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type RenderParams, type Role, type SummaryAdParams, type UserObject };
|
|
561
|
+
export { type Ad, type AdParams, type AdRequestBase, type AdResponse, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type Placement, type PlacementObject, type RenderContextObject, type RenderParams, type Role, type SummaryAdParams, type UserObject };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,58 @@ type Role = 'user' | 'assistant';
|
|
|
8
8
|
* @description Used for demographic targeting of advertisements
|
|
9
9
|
*/
|
|
10
10
|
type Gender = 'male' | 'female' | 'other';
|
|
11
|
+
/**
|
|
12
|
+
* Placement positions for ad rendering
|
|
13
|
+
* @description Specifies where ads should appear relative to the AI response
|
|
14
|
+
*/
|
|
15
|
+
type Placement = 'above_response' | 'below_response' | 'inline_response' | 'left_response' | 'right_response';
|
|
16
|
+
/**
|
|
17
|
+
* Individual ad placement specification
|
|
18
|
+
* @description Defines a single ad slot with its position and optional tracking ID
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const placement: PlacementObject = {
|
|
22
|
+
* placement: 'below_response',
|
|
23
|
+
* placement_id: 'sidebar-1'
|
|
24
|
+
* };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
interface PlacementObject {
|
|
28
|
+
/** Position where the ad should appear (required) */
|
|
29
|
+
placement: Placement;
|
|
30
|
+
/** Optional tracking ID for this specific ad slot */
|
|
31
|
+
placement_id?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Describes how your app will display the ad
|
|
35
|
+
* @description Contains placement array and rendering capabilities for ad customization
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* const renderContext: RenderContextObject = {
|
|
39
|
+
* placements: [
|
|
40
|
+
* { placement: 'below_response' },
|
|
41
|
+
* { placement: 'right_response', placement_id: 'sidebar' }
|
|
42
|
+
* ],
|
|
43
|
+
* max_ad_length: 200
|
|
44
|
+
* };
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
interface RenderContextObject {
|
|
48
|
+
/** Where you plan to show the ad(s). Array of 1-3 placements, must match numAds. */
|
|
49
|
+
placements: PlacementObject[];
|
|
50
|
+
/** Character limit you can display, so we don't send copy that gets truncated */
|
|
51
|
+
max_ad_length?: number;
|
|
52
|
+
/** Whether you can render markdown-formatted text */
|
|
53
|
+
supports_markdown?: boolean;
|
|
54
|
+
/** Whether you can render clickable links */
|
|
55
|
+
supports_links?: boolean;
|
|
56
|
+
/** Whether you can display images (brand logos, product images) */
|
|
57
|
+
supports_images?: boolean;
|
|
58
|
+
/** Whether you can render CTA buttons */
|
|
59
|
+
supports_cta_button?: boolean;
|
|
60
|
+
/** Additional render context properties (supports JSON objects) */
|
|
61
|
+
[key: string]: PlacementObject[] | string | number | boolean | object | null | undefined;
|
|
62
|
+
}
|
|
11
63
|
/**
|
|
12
64
|
* Represents a single message in a conversation
|
|
13
65
|
* @description Used to provide conversation context for contextual ad targeting
|
|
@@ -39,16 +91,18 @@ interface MessageObject {
|
|
|
39
91
|
* ```
|
|
40
92
|
*/
|
|
41
93
|
interface DeviceObject {
|
|
42
|
-
/** User's IP address for geo-targeting */
|
|
94
|
+
/** User's IP address for geo-targeting (required) */
|
|
43
95
|
ip: string;
|
|
96
|
+
/** Browser user-agent string (optional for non-web publishers like IDEs, CLIs, mobile apps) */
|
|
97
|
+
ua?: string;
|
|
44
98
|
/** ISO 3166-1 alpha-2 country code (e.g., 'US', 'GB', 'DE') */
|
|
45
|
-
country
|
|
46
|
-
/** User agent string from the browser */
|
|
47
|
-
ua: string;
|
|
99
|
+
country?: string;
|
|
48
100
|
/** Operating system name (e.g., 'macOS', 'Windows', 'iOS', 'Android') */
|
|
49
101
|
os?: string;
|
|
50
102
|
/** Identifier for Advertisers (mobile advertising ID) */
|
|
51
103
|
ifa?: string;
|
|
104
|
+
/** Additional device properties (timezone, locale, browser, device_type, screen dimensions, etc.) */
|
|
105
|
+
[key: string]: string | number | boolean | undefined;
|
|
52
106
|
}
|
|
53
107
|
/**
|
|
54
108
|
* User profile information for ad targeting
|
|
@@ -64,7 +118,7 @@ interface DeviceObject {
|
|
|
64
118
|
* ```
|
|
65
119
|
*/
|
|
66
120
|
interface UserObject {
|
|
67
|
-
/** Unique user identifier for
|
|
121
|
+
/** Unique user identifier for improving ad relevance */
|
|
68
122
|
uid?: string;
|
|
69
123
|
/** User's gender for demographic targeting */
|
|
70
124
|
gender?: Gender;
|
|
@@ -72,6 +126,8 @@ interface UserObject {
|
|
|
72
126
|
age?: string;
|
|
73
127
|
/** Comma-separated keywords representing user interests */
|
|
74
128
|
keywords?: string;
|
|
129
|
+
/** Additional user properties (email, subscription_tier, user_interests, company_size, etc.) */
|
|
130
|
+
[key: string]: string | string[] | number | boolean | Gender | undefined;
|
|
75
131
|
}
|
|
76
132
|
/**
|
|
77
133
|
* Parameters for requesting an advertisement
|
|
@@ -84,7 +140,12 @@ interface UserObject {
|
|
|
84
140
|
* { role: 'assistant', content: 'What is your budget?' }
|
|
85
141
|
* ],
|
|
86
142
|
* sessionId: 'session-123',
|
|
143
|
+
* numAds: 1,
|
|
144
|
+
* render_context: {
|
|
145
|
+
* placements: [{ placement: 'below_response' }]
|
|
146
|
+
* },
|
|
87
147
|
* userId: 'user-456',
|
|
148
|
+
* testAd: true,
|
|
88
149
|
* user: { gender: 'male', age: '25-34' },
|
|
89
150
|
* device: { ip: '1.2.3.4', country: 'US', ua: 'Mozilla/5.0...' },
|
|
90
151
|
* excludedTopics: ['politics'],
|
|
@@ -95,8 +156,12 @@ interface UserObject {
|
|
|
95
156
|
interface AdParams {
|
|
96
157
|
/** Array of conversation messages for contextual targeting (required) */
|
|
97
158
|
messages: MessageObject[];
|
|
98
|
-
/** Session identifier for
|
|
99
|
-
sessionId
|
|
159
|
+
/** Session identifier for ad relevance (required) */
|
|
160
|
+
sessionId: string;
|
|
161
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
162
|
+
render_context: RenderContextObject;
|
|
163
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
164
|
+
numAds?: number;
|
|
100
165
|
/** Unique user identifier */
|
|
101
166
|
userId?: string;
|
|
102
167
|
/** Device and location information */
|
|
@@ -107,8 +172,6 @@ interface AdParams {
|
|
|
107
172
|
excludedTopics?: string[];
|
|
108
173
|
/** Minimum relevancy score threshold (0-1). Higher = more relevant but fewer ads */
|
|
109
174
|
relevancy?: number | null;
|
|
110
|
-
/** Number of ads to return (1-3, default 1) */
|
|
111
|
-
numAds?: number;
|
|
112
175
|
/** Returns a test ad when true */
|
|
113
176
|
testAd?: boolean;
|
|
114
177
|
/**
|
|
@@ -185,8 +248,12 @@ interface ApiErrorResponse {
|
|
|
185
248
|
* Base fields shared across all ad requests.
|
|
186
249
|
*/
|
|
187
250
|
interface AdRequestBase {
|
|
188
|
-
/** Session identifier for
|
|
189
|
-
sessionId
|
|
251
|
+
/** Session identifier for ad relevance (required) */
|
|
252
|
+
sessionId: string;
|
|
253
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
254
|
+
render_context: RenderContextObject;
|
|
255
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
256
|
+
numAds?: number;
|
|
190
257
|
/** Unique user identifier */
|
|
191
258
|
userId?: string;
|
|
192
259
|
/** Device and location information */
|
|
@@ -197,8 +264,6 @@ interface AdRequestBase {
|
|
|
197
264
|
excludedTopics?: string[];
|
|
198
265
|
/** Minimum relevancy score threshold (0-1) */
|
|
199
266
|
relevancy?: number | null;
|
|
200
|
-
/** Number of ads to return (1-3, default 1) */
|
|
201
|
-
numAds?: number;
|
|
202
267
|
/** Returns a test ad when true */
|
|
203
268
|
testAd?: boolean;
|
|
204
269
|
/** Additional custom fields */
|
|
@@ -221,13 +286,16 @@ interface NonContextualAdParams extends AdRequestBase {
|
|
|
221
286
|
/**
|
|
222
287
|
* POST /api/v1/bid
|
|
223
288
|
* @description Two-phase bid request. Returns bid price and bidId.
|
|
224
|
-
* @note Does NOT extend AdRequestBaseV1 - has its own field set.
|
|
225
289
|
*/
|
|
226
290
|
interface BidParams {
|
|
227
291
|
/** Array of conversation messages (required) */
|
|
228
292
|
messages: MessageObject[];
|
|
229
|
-
/** Session identifier */
|
|
230
|
-
sessionId
|
|
293
|
+
/** Session identifier for ad relevance (required) */
|
|
294
|
+
sessionId: string;
|
|
295
|
+
/** Render context with placements array (required). Length of placements must match numAds. */
|
|
296
|
+
render_context: RenderContextObject;
|
|
297
|
+
/** Number of ads to return (1-3). Must match render_context.placements length. */
|
|
298
|
+
numAds?: number;
|
|
231
299
|
/** Unique user identifier */
|
|
232
300
|
userId?: string;
|
|
233
301
|
/** Chat/conversation identifier */
|
|
@@ -304,6 +372,10 @@ interface ClientParams {
|
|
|
304
372
|
* { role: 'user', content: 'What laptop should I buy?' }
|
|
305
373
|
* ],
|
|
306
374
|
* sessionId: 'session-123',
|
|
375
|
+
* numAds: 1,
|
|
376
|
+
* render_context: {
|
|
377
|
+
* placements: [{ placement: 'below_response' }]
|
|
378
|
+
* }
|
|
307
379
|
* });
|
|
308
380
|
*
|
|
309
381
|
* if (response) {
|
|
@@ -370,6 +442,10 @@ declare class Client {
|
|
|
370
442
|
* { role: 'assistant', content: 'What is your budget range?' }
|
|
371
443
|
* ],
|
|
372
444
|
* sessionId: 'session-123',
|
|
445
|
+
* numAds: 1,
|
|
446
|
+
* render_context: {
|
|
447
|
+
* placements: [{ placement: 'below_response' }]
|
|
448
|
+
* },
|
|
373
449
|
* userId: 'user-456',
|
|
374
450
|
* });
|
|
375
451
|
*
|
|
@@ -384,6 +460,11 @@ declare class Client {
|
|
|
384
460
|
* const response = await client.getAd({
|
|
385
461
|
* messages: [...],
|
|
386
462
|
* sessionId: 'session-123',
|
|
463
|
+
* numAds: 1,
|
|
464
|
+
* render_context: {
|
|
465
|
+
* placements: [{ placement: 'below_response' }],
|
|
466
|
+
* max_ad_length: 200
|
|
467
|
+
* },
|
|
387
468
|
* userId: 'user-456',
|
|
388
469
|
* user: {
|
|
389
470
|
* uid: 'user-123',
|
|
@@ -402,7 +483,12 @@ declare class Client {
|
|
|
402
483
|
*
|
|
403
484
|
* @example Handling the response
|
|
404
485
|
* ```typescript
|
|
405
|
-
* const response = await client.getAd({
|
|
486
|
+
* const response = await client.getAd({
|
|
487
|
+
* messages,
|
|
488
|
+
* sessionId: '...',
|
|
489
|
+
* numAds: 1,
|
|
490
|
+
* render_context: { placements: [{ placement: 'below_response' }] }
|
|
491
|
+
* });
|
|
406
492
|
*
|
|
407
493
|
* if (response) {
|
|
408
494
|
* const ad = response.ads[0];
|
|
@@ -433,10 +519,10 @@ declare class Client {
|
|
|
433
519
|
* @description Fetches ads without context matching. Useful for brand awareness placements.
|
|
434
520
|
* Returns null if no ad is available or on error.
|
|
435
521
|
*
|
|
436
|
-
* @param params -
|
|
522
|
+
* @param params - Request parameters (sessionId required)
|
|
437
523
|
* @returns Promise resolving to AdResponse or null if no ad available
|
|
438
524
|
*/
|
|
439
|
-
nonContextualAd(params
|
|
525
|
+
nonContextualAd(params: NonContextualAdParams): Promise<AdResponse | null>;
|
|
440
526
|
/**
|
|
441
527
|
* Request a bid price for contextual ad placement
|
|
442
528
|
*
|
|
@@ -472,4 +558,4 @@ declare class Client {
|
|
|
472
558
|
private handleError;
|
|
473
559
|
}
|
|
474
560
|
|
|
475
|
-
export { type Ad, type AdParams, type AdRequestBase, type AdResponse, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type RenderParams, type Role, type SummaryAdParams, type UserObject };
|
|
561
|
+
export { type Ad, type AdParams, type AdRequestBase, type AdResponse, type ApiErrorResponse, type BidParams, type BidResponse, Client, type ClientParams, type DeviceObject, type Gender, type MessageObject, type NonContextualAdParams, type Placement, type PlacementObject, type RenderContextObject, type RenderParams, type Role, type SummaryAdParams, type UserObject };
|
package/dist/index.js
CHANGED
|
@@ -90,6 +90,10 @@ var Client = class {
|
|
|
90
90
|
* { role: 'assistant', content: 'What is your budget range?' }
|
|
91
91
|
* ],
|
|
92
92
|
* sessionId: 'session-123',
|
|
93
|
+
* numAds: 1,
|
|
94
|
+
* render_context: {
|
|
95
|
+
* placements: [{ placement: 'below_response' }]
|
|
96
|
+
* },
|
|
93
97
|
* userId: 'user-456',
|
|
94
98
|
* });
|
|
95
99
|
*
|
|
@@ -104,6 +108,11 @@ var Client = class {
|
|
|
104
108
|
* const response = await client.getAd({
|
|
105
109
|
* messages: [...],
|
|
106
110
|
* sessionId: 'session-123',
|
|
111
|
+
* numAds: 1,
|
|
112
|
+
* render_context: {
|
|
113
|
+
* placements: [{ placement: 'below_response' }],
|
|
114
|
+
* max_ad_length: 200
|
|
115
|
+
* },
|
|
107
116
|
* userId: 'user-456',
|
|
108
117
|
* user: {
|
|
109
118
|
* uid: 'user-123',
|
|
@@ -122,7 +131,12 @@ var Client = class {
|
|
|
122
131
|
*
|
|
123
132
|
* @example Handling the response
|
|
124
133
|
* ```typescript
|
|
125
|
-
* const response = await client.getAd({
|
|
134
|
+
* const response = await client.getAd({
|
|
135
|
+
* messages,
|
|
136
|
+
* sessionId: '...',
|
|
137
|
+
* numAds: 1,
|
|
138
|
+
* render_context: { placements: [{ placement: 'below_response' }] }
|
|
139
|
+
* });
|
|
126
140
|
*
|
|
127
141
|
* if (response) {
|
|
128
142
|
* const ad = response.ads[0];
|
|
@@ -194,10 +208,10 @@ var Client = class {
|
|
|
194
208
|
* @description Fetches ads without context matching. Useful for brand awareness placements.
|
|
195
209
|
* Returns null if no ad is available or on error.
|
|
196
210
|
*
|
|
197
|
-
* @param params -
|
|
211
|
+
* @param params - Request parameters (sessionId required)
|
|
198
212
|
* @returns Promise resolving to AdResponse or null if no ad available
|
|
199
213
|
*/
|
|
200
|
-
async nonContextualAd(params
|
|
214
|
+
async nonContextualAd(params) {
|
|
201
215
|
try {
|
|
202
216
|
const body = {
|
|
203
217
|
...params,
|
package/dist/index.mjs
CHANGED
|
@@ -54,6 +54,10 @@ var Client = class {
|
|
|
54
54
|
* { role: 'assistant', content: 'What is your budget range?' }
|
|
55
55
|
* ],
|
|
56
56
|
* sessionId: 'session-123',
|
|
57
|
+
* numAds: 1,
|
|
58
|
+
* render_context: {
|
|
59
|
+
* placements: [{ placement: 'below_response' }]
|
|
60
|
+
* },
|
|
57
61
|
* userId: 'user-456',
|
|
58
62
|
* });
|
|
59
63
|
*
|
|
@@ -68,6 +72,11 @@ var Client = class {
|
|
|
68
72
|
* const response = await client.getAd({
|
|
69
73
|
* messages: [...],
|
|
70
74
|
* sessionId: 'session-123',
|
|
75
|
+
* numAds: 1,
|
|
76
|
+
* render_context: {
|
|
77
|
+
* placements: [{ placement: 'below_response' }],
|
|
78
|
+
* max_ad_length: 200
|
|
79
|
+
* },
|
|
71
80
|
* userId: 'user-456',
|
|
72
81
|
* user: {
|
|
73
82
|
* uid: 'user-123',
|
|
@@ -86,7 +95,12 @@ var Client = class {
|
|
|
86
95
|
*
|
|
87
96
|
* @example Handling the response
|
|
88
97
|
* ```typescript
|
|
89
|
-
* const response = await client.getAd({
|
|
98
|
+
* const response = await client.getAd({
|
|
99
|
+
* messages,
|
|
100
|
+
* sessionId: '...',
|
|
101
|
+
* numAds: 1,
|
|
102
|
+
* render_context: { placements: [{ placement: 'below_response' }] }
|
|
103
|
+
* });
|
|
90
104
|
*
|
|
91
105
|
* if (response) {
|
|
92
106
|
* const ad = response.ads[0];
|
|
@@ -158,10 +172,10 @@ var Client = class {
|
|
|
158
172
|
* @description Fetches ads without context matching. Useful for brand awareness placements.
|
|
159
173
|
* Returns null if no ad is available or on error.
|
|
160
174
|
*
|
|
161
|
-
* @param params -
|
|
175
|
+
* @param params - Request parameters (sessionId required)
|
|
162
176
|
* @returns Promise resolving to AdResponse or null if no ad available
|
|
163
177
|
*/
|
|
164
|
-
async nonContextualAd(params
|
|
178
|
+
async nonContextualAd(params) {
|
|
165
179
|
try {
|
|
166
180
|
const body = {
|
|
167
181
|
...params,
|