Skip to content

0xARYA/taboola-backstage-sdk

Repository files navigation

Taboola Backstage SDK

npm version License: MIT TypeScript Node.js

A comprehensive TypeScript SDK for the Taboola Backstage API. Manage campaigns, ads, targeting, audiences, pixel tracking, and reporting programmatically with full type safety.

Features

  • Full TypeScript Support — Complete type definitions for all API endpoints, requests, and responses
  • Automatic Authentication — OAuth2 token management with automatic refresh
  • Comprehensive API Coverage — Campaigns, Items, Targeting, Pixel, Reports, Audiences, and more
  • Custom Error Classes — Typed errors for auth, validation, rate limiting, and not found scenarios
  • Built-in Retry Logic — Exponential backoff for transient failures
  • Dual Module Support — Works with both ESM and CommonJS

Installation

npm install taboola-backstage-sdk
yarn add taboola-backstage-sdk
pnpm add taboola-backstage-sdk

Quick Start

import { TaboolaClient } from 'taboola-backstage-sdk';

const client = new TaboolaClient({
  clientId: process.env.TABOOLA_CLIENT_ID,
  clientSecret: process.env.TABOOLA_CLIENT_SECRET,
});

// Get your account
const account = await client.accounts.getCurrent();
console.log('Account:', account.account_id);

// List campaigns
const { results: campaigns } = await client.campaigns.list(account.account_id);
console.log(`Found ${campaigns.length} campaigns`);

// Get campaign performance report
const report = await client.reports.campaignSummary(account.account_id, 'day', {
  start_date: '2024-01-01',
  end_date: '2024-01-31',
});

Configuration

const client = new TaboolaClient({
  // Required
  clientId: string,
  clientSecret: string,

  // Optional
  baseUrl?: string,    // API base URL (default: production)
  timeout?: number,    // Request timeout in ms (default: 30000)
  retries?: number,    // Retry attempts for failed requests (default: 3)
  debug?: boolean,     // Enable request/response logging
});

API Reference

Accounts

// Get current account
const account = await client.accounts.getCurrent();

// Get all allowed accounts
const { results } = await client.accounts.getAllowed();

// Get advertisers in a network
const { results } = await client.accounts.getNetworkAdvertisers('network-id');

Campaigns

// List campaigns
const { results } = await client.campaigns.list('account-id', {
  page: 1,
  pageSize: 50,
});

// Get single campaign
const campaign = await client.campaigns.get('account-id', 'campaign-id');

// Create campaign
const campaign = await client.campaigns.create('account-id', {
  name: 'My Campaign',
  branding_text: 'My Brand',
  cpc: 0.50,
  spending_limit: 1000,
  spending_limit_model: 'MONTHLY',
  marketing_objective: 'DRIVE_WEBSITE_TRAFFIC',
});

// Update campaign (partial updates - only specified fields are changed)
await client.campaigns.update('account-id', 'campaign-id', {
  cpc: 0.75,
  daily_cap: 500,
  country_targeting: {
    type: 'INCLUDE',
    value: ['US', 'CA', 'GB'],
  },
  platform_targeting: {
    type: 'INCLUDE',
    value: ['DESK', 'PHON'],
  },
});

// Pause / Unpause
await client.campaigns.pause('account-id', 'campaign-id');
await client.campaigns.unpause('account-id', 'campaign-id');

// Delete
await client.campaigns.delete('account-id', 'campaign-id');

// Duplicate
const copy = await client.campaigns.duplicate('account-id', 'campaign-id', 'Copy Name');

// Bulk update
await client.campaigns.bulkUpdate('account-id', {
  campaigns: [
    { campaign_id: '123', update: { is_active: false } },
    { campaign_id: '456', update: { cpc: 0.60 } },
  ],
});

// List campaigns (base/lightweight)
const { results: base } = await client.campaigns.listBase('account-id');

// Get publisher targeting whitelist
const whitelist = await client.campaigns.getTargetingWhitelist('account-id', 'campaign-id');

Items (Ads)

// List items
const { results } = await client.items.list('account-id', 'campaign-id');

// Get single item
const item = await client.items.get('account-id', 'campaign-id', 'item-id');

// Create item (static ad - only url accepted, starts in CRAWLING state)
const item = await client.items.create('account-id', 'campaign-id', {
  url: 'https://example.com/landing',
});
// Poll until item.status changes from CRAWLING to RUNNING, then update fields

// Update item (static or motion ad - partial updates supported)
await client.items.update('account-id', 'campaign-id', 'item-id', {
  title: 'Updated Title',
  url: 'https://example.com/new-landing-page',
});

// Update motion ad with video
await client.items.update('account-id', 'campaign-id', 'motion-ad-id', {
  title: 'Updated Motion Ad',
  performance_video_data: {
    video_url: 'https://example.com/video.mp4',
    fallback_url: 'https://example.com/fallback.jpg',
  },
});

// Pause / Unpause
await client.items.pause('account-id', 'campaign-id', 'item-id');
await client.items.unpause('account-id', 'campaign-id', 'item-id');

// Delete
await client.items.delete('account-id', 'campaign-id', 'item-id');

// Bulk create (supports both static and motion ads with full field set)
const { results } = await client.items.bulkCreate('account-id', 'campaign-id', {
  items: [
    { url: 'https://example.com/1', title: 'Title 1', thumbnail_url: '...' },
    { url: 'https://example.com/2', title: 'Title 2', thumbnail_url: '...' },
  ],
});

Targeting

// Postal code targeting
const postal = await client.targeting.getPostalCodes('account-id', 'campaign-id');
await client.targeting.updatePostalCodes('account-id', 'campaign-id', {
  type: 'INCLUDE',
  values: [
    { postal_code: '10001', country: 'US' },
    { postal_code: '10002', country: 'US' },
  ],
});

// Marketplace audience targeting
const audiences = await client.targeting.getMarketplaceAudiences('account-id', 'campaign-id');
await client.targeting.updateMarketplaceAudiences('account-id', 'campaign-id', {
  type: 'INCLUDE',
  collection: [{ id: 'segment-123' }],
});

// Custom audience targeting
const custom = await client.targeting.getCustomAudiences('account-id', 'campaign-id');

// Lookalike audience targeting
const lookalike = await client.targeting.getLookalikeAudiences('account-id', 'campaign-id');

// Contextual targeting
const contextual = await client.targeting.getContextual('account-id', 'campaign-id');
await client.targeting.updateContextual('account-id', 'campaign-id', {
  type: 'INCLUDE',
  collection: [{ id: 'context-456' }],
});

// First party audience targeting
const firstParty = await client.targeting.getFirstPartyAudiences('account-id', 'campaign-id');

// Marking labels (pixel retargeting) targeting
const labels = await client.targeting.getMarkingLabels('account-id', 'campaign-id');
await client.targeting.updateMarkingLabels('account-id', 'campaign-id', {
  type: 'EXISTS',
  collection: ['label-1', 'label-2'],
});

Pixel API

Manage conversion tracking and custom audience rules.

// List conversion rules
const rules = await client.pixel.listConversionRules('account-id');

// Get single conversion rule
const rule = await client.pixel.getConversionRule('account-id', 'rule-id');

// Create conversion rule (URL-based)
const rule = await client.pixel.createConversionRule('account-id', {
  display_name: 'Purchase Completed',
  type: 'BASIC',
  category: 'MAKE_PURCHASE',
  condition: {
    property: 'URL',
    predicate: 'CONTAINS',
    value: '/thank-you',
    children: [],
  },
  effects: [{ type: 'REVENUE', data: '15' }],
  look_back_window: 30,
  view_through_look_back_window: 1,
});

// Archive / Unarchive
await client.pixel.archiveConversionRule('account-id', 'rule-id');
await client.pixel.unarchiveConversionRule('account-id', 'rule-id');

// Custom audience rules
const audienceRules = await client.pixel.listCustomAudienceRules('account-id');

const audienceRule = await client.pixel.createCustomAudienceRule('account-id', {
  display_name: 'Cart Abandoners',
  conditions: [
    { type: 'EVENT_NAME', operator: 'EQUALS', value: 'add_to_cart' },
  ],
  ttl_days: 7,
});

// Pause / Resume / Archive
await client.pixel.pauseCustomAudienceRule('account-id', 'rule-id');
await client.pixel.resumeCustomAudienceRule('account-id', 'rule-id');
await client.pixel.archiveCustomAudienceRule('account-id', 'rule-id');

Reports

// Campaign summary report (by dimension)
const report = await client.reports.campaignSummary('account-id', 'day', {
  start_date: '2024-01-01',
  end_date: '2024-01-31',
});

// Available dimensions: 'day', 'week', 'month', 'campaign_breakdown', 'site_breakdown',
//   'country_breakdown', 'platform_breakdown', 'by_hour_of_day', 'region_breakdown',
//   'dma_breakdown', 'campaign_day_breakdown', 'campaign_site_day_breakdown', and more
const byPlatform = await client.reports.campaignSummary('account-id', 'platform_breakdown', {
  start_date: '2024-01-01',
  end_date: '2024-01-31',
  campaign: '12345', // Optional filter
});

// Report data
for (const row of report.results) {
  console.log(`${row.date}: ${row.clicks} clicks, $${row.spent} spent, ${row.ctr}% CTR`);
}

// Top campaign content report
const topContent = await client.reports.topCampaignContent('account-id', {
  start_date: '2024-01-01',
  end_date: '2024-01-31',
  limit: 100,
});

// Realtime campaign report (rate limited: 10 req/min)
const realtime = await client.reports.realtimeCampaign('account-id', 'by_campaign', {
  start_date: '2024-01-15T00:00:00',
  end_date: '2024-01-15T23:59:59',
});

// Realtime ads report (requires item IDs)
const realtimeAds = await client.reports.realtimeAds('account-id', 'by_item', {
  start_date: '2024-01-15T00:00:00',
  end_date: '2024-01-15T23:59:59',
  item: '1001,1002',
});

Publishers

// List available publishers (requires admin network)
const publishers = await client.publishers.list('account-id');

// Get blocked publishers
const blocked = await client.publishers.getBlocked('account-id');

// Block / Unblock publishers
await client.publishers.blockPublisher('account-id', 'site.com');
await client.publishers.unblockPublisher('account-id', 'site.com');

// Bulk update blocked publishers
await client.publishers.updateBlocked('account-id', {
  sites: ['site1.com', 'site2.com'],
});

// Clear all blocks
await client.publishers.clearBlocked('account-id');

Dictionary (Reference Data)

// Geographic data
const countries = await client.dictionary.getCountries();
const regions = await client.dictionary.getRegions('US');
const dmas = await client.dictionary.getDMAs('US');

// Platform/device data
const platforms = await client.dictionary.getPlatforms();

// Audience segments
const marketplace = await client.dictionary.getMarketplaceAudiences('account-id');
const contextual = await client.dictionary.getContextualSegments('account-id');

Combined Audiences

// List available audiences for targeting
const available = await client.combinedAudiences.listAvailable('account-id');

// List combined audiences
const audiences = await client.combinedAudiences.list('account-id');

// Get single combined audience
const audience = await client.combinedAudiences.get('account-id', 'audience-id');

// Create combined audience
const audience = await client.combinedAudiences.create('account-id', {
  name: 'High Value Users',
  rules: [
    { type: 'INCLUDE', audience_id: 'audience-1' },
    { type: 'EXCLUDE', audience_id: 'audience-2' },
  ],
});

Shared Budgets

// List shared budgets (base fields)
const { results } = await client.sharedBudgets.listBase('account-id');

// Get a shared budget
const budget = await client.sharedBudgets.get('account-id', 'budget-id');

// Create shared budget
const budget = await client.sharedBudgets.create('account-id', {
  name: 'Q1 Budget',
  marketing_objective: 'DRIVE_WEBSITE_TRAFFIC',
  spending_limit_model: 'MONTHLY',
  spending_limit: 5000,
  daily_cap: 200,
});

// Update shared budget
await client.sharedBudgets.update('account-id', 'budget-id', {
  spending_limit: 10000,
});

First Party Audiences

// List first party audiences
const audiences = await client.firstPartyAudiences.list('account-id');

// Get single audience
const audience = await client.firstPartyAudiences.get('account-id', 'audience-id');

// Create first party audience
const audience = await client.firstPartyAudiences.create('account-id', {
  name: 'My Audience',
  ttl_in_days: 30,
});

// Add/remove users
await client.firstPartyAudiences.addUsers('account-id', 'audience-id', {
  operation: 'ADD',
  users: [
    { type: 'EMAIL_SHA256', id: 'hashed-email-1' },
    { type: 'EMAIL_SHA256', id: 'hashed-email-2' },
  ],
});

Error Handling

The SDK provides typed error classes for different scenarios:

import {
  TaboolaError,
  TaboolaAuthError,
  TaboolaValidationError,
  TaboolaNotFoundError,
  TaboolaRateLimitError,
  TaboolaForbiddenError,
} from 'taboola-backstage-sdk';

try {
  await client.campaigns.get('account-id', 'invalid-id');
} catch (error) {
  if (error instanceof TaboolaNotFoundError) {
    console.error('Campaign not found');
  } else if (error instanceof TaboolaAuthError) {
    console.error('Authentication failed');
  } else if (error instanceof TaboolaValidationError) {
    console.error('Validation error:', error.fieldErrors);
  } else if (error instanceof TaboolaRateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof TaboolaForbiddenError) {
    console.error('Access denied');
  } else if (error instanceof TaboolaError) {
    console.error(`API error: ${error.message} (${error.statusCode})`);
  }
}

TypeScript

All types are exported for use in your application:

import type {
  // Core types
  Campaign,
  CampaignBase,
  CampaignItem,
  Account,
  SharedBudget,

  // Request types
  CreateCampaignRequest,
  UpdateCampaignRequest,
  CreateItemRequest,
  BulkCreateItemData,
  CreateSharedBudgetRequest,

  // Report types
  CampaignSummaryReport,
  CampaignSummaryRow,
  RealtimeCampaignReport,

  // Targeting types
  PostalCodeTargeting,
  AudienceTargeting,
  MarkingLabelsTargeting,

  // Pixel types
  ConversionRule,
  CustomAudienceRule,

  // Enums / dimension types
  MarketingObjective,
  BidStrategy,
  CampaignStatus,
  ItemStatus,
  ReportDimension,
  RealtimeCampaignDimension,
} from 'taboola-backstage-sdk';

CommonJS Usage

const { TaboolaClient } = require('taboola-backstage-sdk');

const client = new TaboolaClient({
  clientId: process.env.TABOOLA_CLIENT_ID,
  clientSecret: process.env.TABOOLA_CLIENT_SECRET,
});

Requirements

  • Node.js 18.0.0 or higher

API Documentation

For detailed API documentation, see the Taboola Backstage API Reference.

License

MIT

Contributing

Contributions are welcome! Please open an issue or submit a pull request.

Links

About

TypeScript SDK for Taboola Backstage API - Campaign management, reporting, and audience targeting

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors