taboola-backstage-sdk 0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Arya Alikhani
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,478 @@
1
+ # Taboola Backstage SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/taboola-backstage-sdk.svg)](https://www.npmjs.com/package/taboola-backstage-sdk)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)](https://www.typescriptlang.org/)
6
+ [![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
7
+
8
+ A comprehensive TypeScript SDK for the [Taboola Backstage API](https://developers.taboola.com/backstage-api/reference). Manage campaigns, ads, targeting, audiences, pixel tracking, and reporting programmatically.
9
+
10
+ ## Features
11
+
12
+ - **Full TypeScript Support** — Complete type definitions for all API endpoints, requests, and responses
13
+ - **Automatic Authentication** — OAuth2 token management with automatic refresh
14
+ - **Comprehensive API Coverage** — Campaigns, Items, Targeting, Pixel, Reports, Audiences, and more
15
+ - **Custom Error Classes** — Typed errors for auth, validation, rate limiting, and not found scenarios
16
+ - **Built-in Retry Logic** — Exponential backoff for transient failures
17
+ - **Dual Module Support** — Works with both ESM and CommonJS
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ npm install taboola-backstage-sdk
23
+ ```
24
+
25
+ ```bash
26
+ yarn add taboola-backstage-sdk
27
+ ```
28
+
29
+ ```bash
30
+ pnpm add taboola-backstage-sdk
31
+ ```
32
+
33
+ ## Quick Start
34
+
35
+ ```typescript
36
+ import { TaboolaClient } from 'taboola-backstage-sdk';
37
+
38
+ const client = new TaboolaClient({
39
+ clientId: process.env.TABOOLA_CLIENT_ID,
40
+ clientSecret: process.env.TABOOLA_CLIENT_SECRET,
41
+ });
42
+
43
+ // Get your account
44
+ const account = await client.accounts.getCurrent();
45
+ console.log('Account:', account.account_id);
46
+
47
+ // List campaigns
48
+ const { results: campaigns } = await client.campaigns.list(account.account_id);
49
+ console.log(`Found ${campaigns.length} campaigns`);
50
+
51
+ // Get campaign performance report
52
+ const report = await client.reports.campaignSummary(account.account_id, 'day', {
53
+ start_date: '2024-01-01',
54
+ end_date: '2024-01-31',
55
+ });
56
+ ```
57
+
58
+ ## Configuration
59
+
60
+ ```typescript
61
+ const client = new TaboolaClient({
62
+ // Required
63
+ clientId: string,
64
+ clientSecret: string,
65
+
66
+ // Optional
67
+ baseUrl?: string, // API base URL (default: production)
68
+ timeout?: number, // Request timeout in ms (default: 30000)
69
+ retries?: number, // Retry attempts for failed requests (default: 3)
70
+ debug?: boolean, // Enable request/response logging
71
+ });
72
+ ```
73
+
74
+ ## API Reference
75
+
76
+ ### Accounts
77
+
78
+ ```typescript
79
+ // Get current account
80
+ const account = await client.accounts.getCurrent();
81
+
82
+ // Get all allowed accounts
83
+ const { results } = await client.accounts.getAllowed();
84
+
85
+ // Get advertisers in a network
86
+ const { results } = await client.accounts.getNetworkAdvertisers('network-id');
87
+ ```
88
+
89
+ ### Campaigns
90
+
91
+ ```typescript
92
+ // List campaigns
93
+ const { results } = await client.campaigns.list('account-id', {
94
+ page: 1,
95
+ pageSize: 50,
96
+ });
97
+
98
+ // Get single campaign
99
+ const campaign = await client.campaigns.get('account-id', 'campaign-id');
100
+
101
+ // Create campaign
102
+ const campaign = await client.campaigns.create('account-id', {
103
+ name: 'My Campaign',
104
+ branding_text: 'My Brand',
105
+ cpc: 0.50,
106
+ spending_limit: 1000,
107
+ spending_limit_model: 'MONTHLY',
108
+ marketing_objective: 'DRIVE_WEBSITE_TRAFFIC',
109
+ });
110
+
111
+ // Update campaign
112
+ await client.campaigns.update('account-id', 'campaign-id', {
113
+ cpc: 0.75,
114
+ daily_cap: 500,
115
+ });
116
+
117
+ // Pause / Unpause
118
+ await client.campaigns.pause('account-id', 'campaign-id');
119
+ await client.campaigns.unpause('account-id', 'campaign-id');
120
+
121
+ // Delete
122
+ await client.campaigns.delete('account-id', 'campaign-id');
123
+
124
+ // Duplicate
125
+ const copy = await client.campaigns.duplicate('account-id', 'campaign-id', 'Copy Name');
126
+
127
+ // Bulk update
128
+ await client.campaigns.bulkUpdate('account-id', {
129
+ campaigns: [
130
+ { campaign_id: '123', update: { is_active: false } },
131
+ { campaign_id: '456', update: { cpc: 0.60 } },
132
+ ],
133
+ });
134
+ ```
135
+
136
+ ### Items (Ads)
137
+
138
+ ```typescript
139
+ // List items
140
+ const { results } = await client.items.list('account-id', 'campaign-id');
141
+
142
+ // Get single item
143
+ const item = await client.items.get('account-id', 'campaign-id', 'item-id');
144
+
145
+ // Create item
146
+ const item = await client.items.create('account-id', 'campaign-id', {
147
+ url: 'https://example.com/landing',
148
+ title: 'Amazing Product - Learn More',
149
+ thumbnail_url: 'https://example.com/image.jpg',
150
+ description: 'Discover our latest offering',
151
+ cta: { cta_type: 'LEARN_MORE' },
152
+ });
153
+
154
+ // Update item
155
+ await client.items.update('account-id', 'campaign-id', 'item-id', {
156
+ title: 'Updated Title',
157
+ });
158
+
159
+ // Pause / Unpause
160
+ await client.items.pause('account-id', 'campaign-id', 'item-id');
161
+ await client.items.unpause('account-id', 'campaign-id', 'item-id');
162
+
163
+ // Delete
164
+ await client.items.delete('account-id', 'campaign-id', 'item-id');
165
+
166
+ // Bulk create
167
+ const { results } = await client.items.bulkCreate('account-id', 'campaign-id', {
168
+ items: [
169
+ { url: 'https://example.com/1', title: 'Title 1', thumbnail_url: '...' },
170
+ { url: 'https://example.com/2', title: 'Title 2', thumbnail_url: '...' },
171
+ ],
172
+ });
173
+ ```
174
+
175
+ ### Targeting
176
+
177
+ ```typescript
178
+ // Postal code targeting
179
+ const postal = await client.targeting.getPostalCodes('account-id', 'campaign-id');
180
+ await client.targeting.updatePostalCodes('account-id', 'campaign-id', {
181
+ type: 'INCLUDE',
182
+ values: [
183
+ { postal_code: '10001', country: 'US' },
184
+ { postal_code: '10002', country: 'US' },
185
+ ],
186
+ });
187
+
188
+ // Marketplace audience targeting
189
+ const audiences = await client.targeting.getMarketplaceAudiences('account-id', 'campaign-id');
190
+ await client.targeting.updateMarketplaceAudiences('account-id', 'campaign-id', {
191
+ type: 'INCLUDE',
192
+ collection: [{ id: 'segment-123' }],
193
+ });
194
+
195
+ // Custom audience targeting
196
+ const custom = await client.targeting.getCustomAudiences('account-id', 'campaign-id');
197
+
198
+ // Lookalike audience targeting
199
+ const lookalike = await client.targeting.getLookalikeAudiences('account-id', 'campaign-id');
200
+
201
+ // Contextual targeting
202
+ const contextual = await client.targeting.getContextual('account-id', 'campaign-id');
203
+ await client.targeting.updateContextual('account-id', 'campaign-id', {
204
+ type: 'INCLUDE',
205
+ collection: [{ id: 'context-456' }],
206
+ });
207
+
208
+ // First party audience targeting
209
+ const firstParty = await client.targeting.getFirstPartyAudiences('account-id', 'campaign-id');
210
+ ```
211
+
212
+ ### Pixel API
213
+
214
+ Manage conversion tracking and custom audience rules.
215
+
216
+ ```typescript
217
+ // List conversion rules
218
+ const rules = await client.pixel.listConversionRules('account-id');
219
+
220
+ // Get single conversion rule
221
+ const rule = await client.pixel.getConversionRule('account-id', 'rule-id');
222
+
223
+ // Create conversion rule
224
+ const rule = await client.pixel.createConversionRule('account-id', {
225
+ display_name: 'Purchase Completed',
226
+ type: 'EVENT_BASED',
227
+ category: 'PURCHASE',
228
+ event_name: 'purchase',
229
+ conditions: [],
230
+ effect: {
231
+ type: 'DYNAMIC_VALUE',
232
+ currency: 'USD',
233
+ value_parameter: 'order_total',
234
+ },
235
+ conversion_window_days: 30,
236
+ view_through_window_days: 1,
237
+ });
238
+
239
+ // Archive / Unarchive
240
+ await client.pixel.archiveConversionRule('account-id', 'rule-id');
241
+ await client.pixel.unarchiveConversionRule('account-id', 'rule-id');
242
+
243
+ // Custom audience rules
244
+ const audienceRules = await client.pixel.listCustomAudienceRules('account-id');
245
+
246
+ const audienceRule = await client.pixel.createCustomAudienceRule('account-id', {
247
+ display_name: 'Cart Abandoners',
248
+ conditions: [
249
+ { type: 'EVENT_NAME', operator: 'EQUALS', value: 'add_to_cart' },
250
+ ],
251
+ ttl_days: 7,
252
+ });
253
+
254
+ // Pause / Resume / Archive
255
+ await client.pixel.pauseCustomAudienceRule('account-id', 'rule-id');
256
+ await client.pixel.resumeCustomAudienceRule('account-id', 'rule-id');
257
+ await client.pixel.archiveCustomAudienceRule('account-id', 'rule-id');
258
+ ```
259
+
260
+ ### Reports
261
+
262
+ ```typescript
263
+ // Campaign summary report (by dimension)
264
+ const report = await client.reports.campaignSummary('account-id', 'day', {
265
+ start_date: '2024-01-01',
266
+ end_date: '2024-01-31',
267
+ });
268
+
269
+ // Available dimensions: 'day', 'week', 'month', 'campaign', 'site', 'country', 'platform'
270
+ const byPlatform = await client.reports.campaignSummary('account-id', 'platform', {
271
+ start_date: '2024-01-01',
272
+ end_date: '2024-01-31',
273
+ campaign: '12345', // Optional filter
274
+ });
275
+
276
+ // Report data
277
+ for (const row of report.results) {
278
+ console.log(`${row.date}: ${row.clicks} clicks, $${row.spent} spent, ${row.ctr}% CTR`);
279
+ }
280
+
281
+ // Top campaign content report
282
+ const topContent = await client.reports.topCampaignContent('account-id', {
283
+ start_date: '2024-01-01',
284
+ end_date: '2024-01-31',
285
+ limit: 100,
286
+ });
287
+
288
+ // Realtime reports
289
+ const realtime = await client.reports.realtimeCampaign('account-id');
290
+ const realtimeAds = await client.reports.realtimeAds('account-id');
291
+ ```
292
+
293
+ ### Publishers
294
+
295
+ ```typescript
296
+ // List available publishers (requires admin network)
297
+ const publishers = await client.publishers.list('account-id');
298
+
299
+ // Get blocked publishers
300
+ const blocked = await client.publishers.getBlocked('account-id');
301
+
302
+ // Block / Unblock publishers
303
+ await client.publishers.blockPublisher('account-id', 'site.com');
304
+ await client.publishers.unblockPublisher('account-id', 'site.com');
305
+
306
+ // Bulk update blocked publishers
307
+ await client.publishers.updateBlocked('account-id', {
308
+ sites: ['site1.com', 'site2.com'],
309
+ });
310
+
311
+ // Clear all blocks
312
+ await client.publishers.clearBlocked('account-id');
313
+ ```
314
+
315
+ ### Dictionary (Reference Data)
316
+
317
+ ```typescript
318
+ // Geographic data
319
+ const countries = await client.dictionary.getCountries();
320
+ const regions = await client.dictionary.getRegions('US');
321
+ const dmas = await client.dictionary.getDMAs('US');
322
+
323
+ // Platform/device data
324
+ const platforms = await client.dictionary.getPlatforms();
325
+
326
+ // Audience segments
327
+ const marketplace = await client.dictionary.getMarketplaceAudiences('account-id');
328
+ const contextual = await client.dictionary.getContextualSegments('account-id');
329
+ ```
330
+
331
+ ### Combined Audiences
332
+
333
+ ```typescript
334
+ // List available audiences for targeting
335
+ const available = await client.combinedAudiences.listAvailable('account-id');
336
+
337
+ // List combined audiences
338
+ const audiences = await client.combinedAudiences.list('account-id');
339
+
340
+ // Get single combined audience
341
+ const audience = await client.combinedAudiences.get('account-id', 'audience-id');
342
+
343
+ // Create combined audience
344
+ const audience = await client.combinedAudiences.create('account-id', {
345
+ name: 'High Value Users',
346
+ rules: [
347
+ { type: 'INCLUDE', audience_id: 'audience-1' },
348
+ { type: 'EXCLUDE', audience_id: 'audience-2' },
349
+ ],
350
+ });
351
+ ```
352
+
353
+ ### First Party Audiences
354
+
355
+ ```typescript
356
+ // List first party audiences
357
+ const audiences = await client.firstPartyAudiences.list('account-id');
358
+
359
+ // Get single audience
360
+ const audience = await client.firstPartyAudiences.get('account-id', 'audience-id');
361
+
362
+ // Create first party audience
363
+ const audience = await client.firstPartyAudiences.create('account-id', {
364
+ name: 'My Audience',
365
+ ttl_in_days: 30,
366
+ });
367
+
368
+ // Add/remove users
369
+ await client.firstPartyAudiences.addUsers('account-id', 'audience-id', {
370
+ operation: 'ADD',
371
+ users: [
372
+ { type: 'EMAIL_SHA256', id: 'hashed-email-1' },
373
+ { type: 'EMAIL_SHA256', id: 'hashed-email-2' },
374
+ ],
375
+ });
376
+ ```
377
+
378
+ ## Error Handling
379
+
380
+ The SDK provides typed error classes for different scenarios:
381
+
382
+ ```typescript
383
+ import {
384
+ TaboolaError,
385
+ TaboolaAuthError,
386
+ TaboolaValidationError,
387
+ TaboolaNotFoundError,
388
+ TaboolaRateLimitError,
389
+ TaboolaForbiddenError,
390
+ } from 'taboola-backstage-sdk';
391
+
392
+ try {
393
+ await client.campaigns.get('account-id', 'invalid-id');
394
+ } catch (error) {
395
+ if (error instanceof TaboolaNotFoundError) {
396
+ console.error('Campaign not found');
397
+ } else if (error instanceof TaboolaAuthError) {
398
+ console.error('Authentication failed');
399
+ } else if (error instanceof TaboolaValidationError) {
400
+ console.error('Validation error:', error.fieldErrors);
401
+ } else if (error instanceof TaboolaRateLimitError) {
402
+ console.error(`Rate limited. Retry after ${error.retryAfter}s`);
403
+ } else if (error instanceof TaboolaForbiddenError) {
404
+ console.error('Access denied');
405
+ } else if (error instanceof TaboolaError) {
406
+ console.error(`API error: ${error.message} (${error.statusCode})`);
407
+ }
408
+ }
409
+ ```
410
+
411
+ ## TypeScript
412
+
413
+ All types are exported for use in your application:
414
+
415
+ ```typescript
416
+ import type {
417
+ // Core types
418
+ Campaign,
419
+ CampaignItem,
420
+ Account,
421
+
422
+ // Request types
423
+ CreateCampaignRequest,
424
+ UpdateCampaignRequest,
425
+ CreateItemRequest,
426
+
427
+ // Report types
428
+ CampaignSummaryReport,
429
+ CampaignSummaryRow,
430
+
431
+ // Targeting types
432
+ PostalCodeTargeting,
433
+ AudienceTargeting,
434
+
435
+ // Pixel types
436
+ ConversionRule,
437
+ CustomAudienceRule,
438
+
439
+ // Enums
440
+ MarketingObjective,
441
+ BidStrategy,
442
+ CampaignStatus,
443
+ ItemStatus,
444
+ } from 'taboola-backstage-sdk';
445
+ ```
446
+
447
+ ## CommonJS Usage
448
+
449
+ ```javascript
450
+ const { TaboolaClient } = require('taboola-backstage-sdk');
451
+
452
+ const client = new TaboolaClient({
453
+ clientId: process.env.TABOOLA_CLIENT_ID,
454
+ clientSecret: process.env.TABOOLA_CLIENT_SECRET,
455
+ });
456
+ ```
457
+
458
+ ## Requirements
459
+
460
+ - Node.js 18.0.0 or higher
461
+
462
+ ## API Documentation
463
+
464
+ For detailed API documentation, see the [Taboola Backstage API Reference](https://developers.taboola.com/backstage-api/reference).
465
+
466
+ ## License
467
+
468
+ MIT
469
+
470
+ ## Contributing
471
+
472
+ Contributions are welcome! Please open an issue or submit a pull request.
473
+
474
+ ## Links
475
+
476
+ - [Taboola Backstage API Documentation](https://developers.taboola.com/backstage-api/reference)
477
+ - [npm Package](https://www.npmjs.com/package/taboola-backstage-sdk)
478
+ - [GitHub Repository](https://github.com/0xARYA/taboola-backstage-sdk)