Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
397 changes: 110 additions & 287 deletions README.md

Large diffs are not rendered by default.

129 changes: 129 additions & 0 deletions docs/brand-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
# Brand Persona Guide

The brand persona is designed for brand identity management within the Scope3 SDK. It provides full CRUD operations for managing brand profiles, including support for brand manifests that define visual identity, tone, and other brand attributes.

## Setup

Configure the client with the `brand` persona:

```typescript
import { Scope3Client } from 'scope3';

const client = new Scope3Client({
apiKey: process.env.SCOPE3_API_KEY!,
persona: 'brand',
});
```

## Brand Management

The brand persona supports the following operations:

- **list** - Retrieve all brands with pagination support
- **get** - Retrieve a specific brand by ID
- **create** - Create a new brand using a manifest URL or inline manifest JSON
- **update** - Update an existing brand
- **delete** - Remove a brand

## Manifest Formats

When creating or updating a brand, you can provide the brand manifest in one of two formats:

- **manifestUrl** - A URL pointing to a hosted JSON manifest file
- **manifestJson** - An inline JSON object containing the manifest data directly

### Brand Manifest Schema

The manifest supports the following fields:

| Field | Description |
|---|---|
| `name` | Brand name |
| `url` | Brand website URL |
| `logos` | Array of logo objects with `url` and `tags` |
| `colors` | Object with color definitions (e.g., `primary`, `secondary`) |
| `fonts` | Object with font definitions (e.g., `primary`, `secondary`) |
| `tone` | Description of the brand voice and tone |
| `tagline` | Brand tagline or slogan |
| `assets` | Additional brand assets |
| `product_catalog` | Product catalog information |
| `disclaimers` | Legal disclaimers and compliance text |
| `industry` | Industry vertical |
| `target_audience` | Description of the target audience |
| `contact` | Contact information |
| `metadata` | Arbitrary key-value metadata |

## Examples

### List Brands

```typescript
const brands = await client.brands.list();

for (const brand of brands.data) {
console.log(`${brand.id}: ${brand.name}`);
}
```

### Create with Manifest URL

Use `manifestUrl` when your brand manifest is hosted externally:

```typescript
await client.brands.create({
manifestUrl: 'https://example.com/brand-manifest.json',
});
```

### Create with Inline Manifest

Use `manifestJson` to provide the manifest data directly:

```typescript
await client.brands.create({
manifestJson: {
name: 'Acme Corp',
url: 'https://acme.com',
logos: [{ url: 'https://acme.com/logo.png', tags: ['primary'] }],
colors: { primary: '#FF6600', secondary: '#333333' },
fonts: { primary: 'Inter', secondary: 'Georgia' },
tone: 'Professional and innovative',
tagline: 'Building the future',
industry: 'Technology',
target_audience: 'Enterprise decision makers',
},
});
```

### Get a Specific Brand

```typescript
const brand = await client.brands.get('brand-123');
console.log(brand.data.name);
```

### Update a Brand

```typescript
await client.brands.update('brand-123', {
manifestJson: { name: 'Acme Corp Updated' },
});
```

### Delete a Brand

```typescript
await client.brands.delete('brand-123');
```

## Pagination

List operations support pagination. Use the cursor returned in the response to fetch additional pages:

```typescript
const firstPage = await client.brands.list();

if (firstPage.nextCursor) {
const secondPage = await client.brands.list({ cursor: firstPage.nextCursor });
}
```
224 changes: 224 additions & 0 deletions docs/buyer-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
# Buyer Persona Guide

## Overview

The buyer persona enables AI-powered programmatic advertising with:

- Advertiser management
- Bundle-based inventory discovery
- 3 campaign types (bundle, performance, audience)
- Reporting and analytics

## Setup

```typescript
import { Scope3Client } from 'scope3';

const client = new Scope3Client({
apiKey: process.env.SCOPE3_API_KEY!,
persona: 'buyer',
});
```

## Full Buyer Workflow

### Step 1: Create an Advertiser

```typescript
const advertiser = await client.advertisers.create({
name: 'Acme Corp',
description: 'Leading widget manufacturer',
});
const advId = advertiser.data.id;
```

### Step 2: Link a Brand

```typescript
const brand = client.advertisers.brand(advId);
await brand.link({ brandId: 'brand-123' });
```

### Step 3: Create a Bundle for Inventory Discovery

```typescript
const bundle = await client.bundles.create({
advertiserId: advId,
channels: ['display', 'video'],
countries: ['US', 'UK'],
budget: 50000,
});
const bundleId = bundle.data.bundleId;
```

### Step 4: Discover Products

```typescript
const discovery = await client.bundles.discoverProducts(bundleId, {
groupLimit: 10,
productsPerGroup: 5,
});

// Browse the product groups
for (const group of discovery.data.productGroups) {
console.log(`${group.groupName}: ${group.productCount} products`);
for (const product of group.products) {
console.log(` - ${product.name} (${product.publisher}) $${product.cpm} CPM`);
}
}
```

### Step 5: Add Products to Bundle

```typescript
const selectedProducts = discovery.data.productGroups[0].products.map(p => ({
productId: p.productId,
salesAgentId: p.salesAgentId,
groupId: discovery.data.productGroups[0].groupId,
groupName: discovery.data.productGroups[0].groupName,
}));

await client.bundles.products(bundleId).add({ products: selectedProducts });
```

### Step 6: Create a Bundle Campaign

```typescript
const campaign = await client.campaigns.createBundle({
advertiserId: advId,
bundleId: bundleId,
name: 'Q1 Display Campaign',
flightDates: { startDate: '2025-01-15', endDate: '2025-03-31' },
budget: { total: 50000, currency: 'USD', pacing: 'EVEN' },
});
```

### Step 7: Execute the Campaign

```typescript
await client.campaigns.execute(campaign.data.id);
```

## Campaign Types

### Bundle Campaigns

Standard campaigns with pre-selected inventory bundles.

```typescript
await client.campaigns.createBundle({ ... });
await client.campaigns.updateBundle(id, { ... });
```

### Performance Campaigns

Goal-oriented campaigns with performance optimization.

```typescript
await client.campaigns.createPerformance({
advertiserId: advId,
name: 'ROAS Campaign',
flightDates: { startDate: '2025-01-15', endDate: '2025-03-31' },
budget: { total: 100000, currency: 'USD' },
performanceConfig: {
objective: 'ROAS',
goals: { targetRoas: 3.5 },
},
});
```

### Audience Campaigns

Signal-based audience targeting (coming soon).

```typescript
await client.campaigns.createAudience({ ... });
```

## Advertiser Sub-Resources

Access sub-resources scoped to an advertiser.

### Conversion Events

```typescript
const events = client.advertisers.conversionEvents(advId);
await events.list();
await events.create({ name: 'Purchase', type: 'PURCHASE', value: 50 });
```

### Creative Sets

```typescript
const sets = client.advertisers.creativeSets(advId);
await sets.list();
await sets.create({ name: 'Holiday Creatives', type: 'display' });
```

### Test Cohorts

```typescript
const cohorts = client.advertisers.testCohorts(advId);
await cohorts.list();
await cohorts.create({ name: 'A/B Test', splitPercentage: 50 });
```

### Reporting

```typescript
const reporting = client.advertisers.reporting(advId);
const report = await reporting.get({ days: 30 });
console.log(`Total spend: $${report.data.totals.spend}`);
```

### Media Buys

```typescript
const buys = client.advertisers.mediaBuys(advId);
const mediaBuys = await buys.list();
```

## Signals

```typescript
const signals = await client.signals.discover();
```

## Buyer Brands

List all brands available:

```typescript
const brands = await client.buyerBrands.list();
```

## Pagination

All list methods support pagination:

```typescript
const page1 = await client.advertisers.list({ take: 10, skip: 0 });
const page2 = await client.advertisers.list({ take: 10, skip: 10 });

// Check pagination info
console.log(`Total: ${page1.pagination.total}, Has more: ${page1.pagination.hasMore}`);
```

## API Response Format

All responses use a standard envelope:

```typescript
// Single item
interface ApiResponse<T> {
data: T;
error?: { code: string; message: string; details?: Record<string, unknown> };
}

// Paginated list
interface PaginatedApiResponse<T> {
data: T[];
pagination: { total: number; take: number; skip: number; hasMore: boolean };
error?: { code: string; message: string; details?: Record<string, unknown> };
}
```
Loading
Loading