@gravity-ai/api 1.1.0 → 1.1.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 +4 -552
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
# @gravity-ai/api
|
|
2
2
|
|
|
3
|
-
The official Node.js/TypeScript SDK for the Gravity AI advertising API.
|
|
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
|
-
---
|
|
3
|
+
The official Node.js/TypeScript SDK for the Gravity AI advertising API.
|
|
22
4
|
|
|
23
5
|
## Installation
|
|
24
6
|
|
|
@@ -26,541 +8,11 @@ The official Node.js/TypeScript SDK for the Gravity AI advertising API. Fetch co
|
|
|
26
8
|
npm install @gravity-ai/api
|
|
27
9
|
```
|
|
28
10
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
## Quick Start
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
import { Client } from '@gravity-ai/api';
|
|
37
|
-
|
|
38
|
-
const client = new Client('your-api-key');
|
|
39
|
-
|
|
40
|
-
const response = await client.getAd({
|
|
41
|
-
messages: [
|
|
42
|
-
{ role: 'user', content: 'What are some good hiking trails?' },
|
|
43
|
-
],
|
|
44
|
-
sessionId: 'session-123',
|
|
45
|
-
userId: 'user-456',
|
|
46
|
-
numAds: 1,
|
|
47
|
-
render_context: {
|
|
48
|
-
placements: [{ placement: 'below_response' }]
|
|
49
|
-
},
|
|
50
|
-
testAd: true,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
if (response) {
|
|
54
|
-
const ad = response.ads[0];
|
|
55
|
-
console.log(ad.adText);
|
|
56
|
-
}
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Migrating from v0
|
|
62
|
-
|
|
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**
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
// Before (v0)
|
|
73
|
-
const ad = await client.getAd({ messages });
|
|
74
|
-
|
|
75
|
-
// After (v1)
|
|
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];
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
---
|
|
88
|
-
|
|
89
|
-
## Client Configuration
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
import { Client } from '@gravity-ai/api';
|
|
93
|
-
|
|
94
|
-
// Basic
|
|
95
|
-
const client = new Client('your-api-key');
|
|
96
|
-
|
|
97
|
-
// Advanced
|
|
98
|
-
const client = new Client('your-api-key', {
|
|
99
|
-
excludedTopics: ['politics', 'religion'], // Global exclusions
|
|
100
|
-
relevancy: 0.6, // Min relevancy threshold (0.1-1)
|
|
101
|
-
});
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
| Option | Type | Default | Description |
|
|
105
|
-
|--------|------|---------|-------------|
|
|
106
|
-
| `endpoint` | `string` | `'https://server.trygravity.ai'` | API endpoint URL |
|
|
107
|
-
| `excludedTopics` | `string[]` | `[]` | Topics to exclude from ad matching |
|
|
108
|
-
| `relevancy` | `number` | `null` | Minimum relevancy score (0.1-1) |
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
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>
|
|
155
|
-
|
|
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
|
|
210
|
-
|
|
211
|
-
```typescript
|
|
212
|
-
const response = await client.getAd({
|
|
213
|
-
// Common fields
|
|
214
|
-
messages: [
|
|
215
|
-
{ role: 'user', content: 'What are the best practices for React performance?' }
|
|
216
|
-
],
|
|
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
|
-
}
|
|
244
|
-
});
|
|
245
|
-
```
|
|
246
|
-
|
|
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
|
-
});
|
|
303
|
-
```
|
|
304
|
-
|
|
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
|
|
323
|
-
|
|
324
|
-
```typescript
|
|
325
|
-
const response = await client.getAd({
|
|
326
|
-
// Common fields
|
|
327
|
-
messages: [
|
|
328
|
-
{ role: 'assistant', content: 'I found several Italian restaurants nearby.' },
|
|
329
|
-
{ role: 'user', content: 'Which one has the best pasta?' }
|
|
330
|
-
],
|
|
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
|
|
345
|
-
user: {
|
|
346
|
-
email: 'user@example.com',
|
|
347
|
-
subscription_tier: 'premium',
|
|
348
|
-
user_created_at: '2023-06-15T00:00:00Z',
|
|
349
|
-
user_interests: ['food', 'dining', 'travel']
|
|
350
|
-
},
|
|
351
|
-
device: {
|
|
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'
|
|
361
|
-
},
|
|
362
|
-
app: {
|
|
363
|
-
version: '2.1.0'
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
---
|
|
369
|
-
|
|
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
|
-
},
|
|
391
|
-
|
|
392
|
-
// Optional fields
|
|
393
|
-
device: {
|
|
394
|
-
ip: '192.168.1.1',
|
|
395
|
-
timezone: 'America/New_York',
|
|
396
|
-
locale: 'en-US'
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
```
|
|
400
|
-
|
|
401
|
-
---
|
|
402
|
-
|
|
403
|
-
## Response Types
|
|
404
|
-
|
|
405
|
-
### AdResponse
|
|
406
|
-
|
|
407
|
-
```typescript
|
|
408
|
-
interface AdResponse {
|
|
409
|
-
ads: Ad[]; // Array of ads (one per placement)
|
|
410
|
-
numAds: number; // Number of ads returned
|
|
411
|
-
totalPayout?: number; // Total payout across all ads
|
|
412
|
-
}
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
### Ad
|
|
416
|
-
|
|
417
|
-
```typescript
|
|
418
|
-
interface Ad {
|
|
419
|
-
adText: string; // Ad copy text
|
|
420
|
-
adId: string; // Unique ad identifier
|
|
421
|
-
title?: string; // Ad title
|
|
422
|
-
brandName?: string; // Brand name
|
|
423
|
-
brandImage?: string; // Brand logo URL
|
|
424
|
-
url?: string; // Landing page URL
|
|
425
|
-
favicon?: string; // Favicon URL
|
|
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)
|
|
429
|
-
}
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### Request Types
|
|
433
|
-
|
|
434
|
-
```typescript
|
|
435
|
-
interface MessageObject {
|
|
436
|
-
role: 'user' | 'assistant';
|
|
437
|
-
content: string;
|
|
438
|
-
}
|
|
439
|
-
|
|
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;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
interface PlacementObject {
|
|
450
|
-
placement: 'above_response' | 'below_response' | 'inline_response' | 'left_response' | 'right_response';
|
|
451
|
-
placement_id?: string;
|
|
452
|
-
}
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
---
|
|
11
|
+
## Documentation
|
|
456
12
|
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
The client returns `null` on failure. Errors are logged to console.
|
|
460
|
-
|
|
461
|
-
```typescript
|
|
462
|
-
const response = await client.getAd({
|
|
463
|
-
messages,
|
|
464
|
-
sessionId: 'session-123',
|
|
465
|
-
numAds: 1,
|
|
466
|
-
render_context: { placements: [{ placement: 'below_response' }] }
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
// Returns null on:
|
|
470
|
-
// - Network errors
|
|
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
|
|
475
|
-
|
|
476
|
-
if (!response) {
|
|
477
|
-
// Handle gracefully - don't break the user experience
|
|
478
|
-
}
|
|
479
|
-
```
|
|
480
|
-
|
|
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 |
|
|
488
|
-
|
|
489
|
-
---
|
|
490
|
-
|
|
491
|
-
## Using with React
|
|
492
|
-
|
|
493
|
-
For React applications, use the companion package `@gravity-ai/react`:
|
|
494
|
-
|
|
495
|
-
```bash
|
|
496
|
-
npm install @gravity-ai/api @gravity-ai/react
|
|
497
|
-
```
|
|
498
|
-
|
|
499
|
-
```tsx
|
|
500
|
-
import { Client } from '@gravity-ai/api';
|
|
501
|
-
import { AdBanner } from '@gravity-ai/react';
|
|
502
|
-
|
|
503
|
-
const client = new Client('your-api-key');
|
|
504
|
-
|
|
505
|
-
function ChatApp() {
|
|
506
|
-
const [ad, setAd] = useState(null);
|
|
507
|
-
|
|
508
|
-
useEffect(() => {
|
|
509
|
-
client.getAd({
|
|
510
|
-
messages,
|
|
511
|
-
sessionId: 'session-123',
|
|
512
|
-
userId: 'user-456',
|
|
513
|
-
numAds: 1,
|
|
514
|
-
render_context: { placements: [{ placement: 'below_response' }] },
|
|
515
|
-
testAd: true,
|
|
516
|
-
}).then(res => setAd(res?.ads[0] || null));
|
|
517
|
-
}, [messages]);
|
|
518
|
-
|
|
519
|
-
return <AdBanner ad={ad} theme="dark" />;
|
|
520
|
-
}
|
|
521
|
-
```
|
|
522
|
-
|
|
523
|
-
---
|
|
524
|
-
|
|
525
|
-
## Best Practices
|
|
526
|
-
|
|
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.
|
|
532
|
-
|
|
533
|
-
4. **Use `testAd: true` during development** — Prevents generating real impressions or clicks.
|
|
534
|
-
|
|
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
|
-
```
|
|
13
|
+
For full documentation, examples, and API reference, visit:
|
|
562
14
|
|
|
563
|
-
|
|
15
|
+
**[https://www.trygravity.ai/api](https://www.trygravity.ai/api)**
|
|
564
16
|
|
|
565
17
|
## License
|
|
566
18
|
|