URL: /code/integrations/reddit-ads · Id: `page:/code/integrations/reddit-ads`

# Reddit Ads

> Your agent promotes the Reddit post that already earned replies, in the subreddits where your buyers talk, signed in as you.

Your agent promotes the Reddit post that already earned replies, in the subreddits where your buyers talk, signed in as you.

```text title="Run it · Ask"
Build a $150 Reddit test promoting my rent-tracking answer in r/Landlord and r/PropertyManagement.
```

```ts title="Run it · SDK"
import { $ } from 'startup-builder'

const result = await $.try.Campaign.create({ venue: 'reddit', objective: 'traffic', audience: { subreddits: ['r/Landlord', 'r/PropertyManagement'] }, budget: { amount: 150, currency: 'USD', per: 'test' }, promote: 'posts/reddit-rent-tracking-answer' })
```

```json title="Run it · Response"
{
  "$type": "Campaign",
  "mode": "try",
  "stored": false,
  "venue": "reddit",
  "adGroups": [
    {
      "subreddit": "r/Landlord",
      "budget": 75
    },
    {
      "subreddit": "r/PropertyManagement",
      "budget": 75
    }
  ],
  "promoting": "posts/reddit-rent-tracking-answer",
  "readAt": "3,000 impressions per ad group",
  "runsBy": "browser",
  "steps": 19
}
```

- **Connect:** Sign in once, 1 grant
- **Runs through:** [A browser agent](/code/integrations#three-ways)
- **First run:** Find the subreddits that hold the threads on your problem, about 0.03¢
- **Sites:** [Reddit](/venues#reddit)

## Connect once
1. Call `Integration.connect` with `system: 'ads'` and `venue: 'reddit'`; a browser window opens on Reddit Ads Manager.
2. Sign in with your Reddit account and pick the ad account; the session is saved to your browser profile.
3. Set the spend on your standing approval with `Mandate.authorize`; Reddit bills your ad account, never the platform.

| Grant | What it unlocks | Scope |
| --- | --- | --- |
| Your saved Ads Manager session | Campaigns, ad groups, promoted posts, budgets and results, in Reddit’s own screens | `browser session: ads.reddit.com` |

| To | Do this |
| --- | --- |
| Pause | `Integration.pause` holds every run that needs your Reddit Ads Manager session; the session stays saved. |
| Reconnect | `Integration.reconnect` opens a browser window where you sign in to Reddit Ads Manager once more; the saved session replaces the old one. |
| Disconnect | `Integration.revoke` deletes the saved Reddit Ads Manager session; every Post and reply it made stays in your records. |

## What your agents do
| Ask | Verb | Runs through | Price |
| --- | --- | --- | --- |
| Build a $150 campaign in r/Landlord and r/PropertyManagement, signed in as me. | [`Campaign.create`](/code/apps/ads/create-campaign) | A browser agent | About 1.6¢ a step |
| Promote my answer that earned 30 replies, as it is, signed in as me. | [`Ad.create`](/code/apps/ads/create-ad) | A browser agent | About 1.6¢ a step |
| Pause the weaker ad group, signed in as me. | [`Campaign.update`](/code/apps/ads/update-campaign) | A browser agent | About 1.6¢ a step |
| Show me impressions, clicks and signups by subreddit, signed in as me. | [`Metric.query`](/code/apps/analytics-and-experiments/query) | A browser agent | About 1.6¢ a step |

Calls on your own account are free; Reddit bills your spend directly.

Reading this site’s public data needs no account: [`Keyword.search`](/code/data/keywords/search) is a Data call (the [three ways a call runs](/code/integrations#three-ways)).

## What it holds
| Noun | The account’s object | When | Which side leads |
| --- | --- | --- | --- |
| [Campaign](https://startupbuilder.dev/business/nouns/campaign) | `campaign and ad groups` | Your agent builds it | Your records |
| [Ad](https://startupbuilder.dev/business/nouns/ad) | `promoted post` | Your agent promotes a post; Reddit’s review sets its status | Your records |
| [Message](https://startupbuilder.dev/business/nouns/message) | `comment` | Someone comments on it | The account |

## Events and webhooks
| Direction | Event |
| --- | --- |
| Emits | `Campaign.created`, `Campaign.updated`, `Ad.created`, `Entry.posted`, `Message.created` |

Any Event can wake a Workflow, and a Watch delivers it to your endpoint, signed ([Events and webhooks](/code/events)).

## Limits
| What | Limit | Call |
| --- | --- | --- |
| Ad review | Reddit reviews every ad; a rejection comes back as `venue-rejected` with the reason | [`Ad.create`](/code/apps/ads/create-ad) |
| Budget floor | The agent reads the minimum Ads Manager shows for your account before it builds, and a budget under it refuses with `venue-rejected` | [`Campaign.create`](/code/apps/ads/create-campaign) |
| Comments on a promoted post | Stay open; each one reaches you as a Message, and your agent drafts the answer | Every call |
| Spend | Your standing approval holds the cap; a change past it waits with `over-mandate` | [`Campaign.update`](/code/apps/ads/update-campaign) |

## Start here
| Move | The rule |
| --- | --- |
| Structure | One campaign, one ad group per subreddit cluster (the 2 to 5 communities where your answers drew replies), promoting the post that already earned replies. |
| Budget | $150 for the first test, split evenly across the ad groups, and no more until one ad group sends a signup. |
| Creative | Promote the post as it is, with the title it earned replies under; a promoted post reads as a post, so it needs no ad copy. |
| Kill rule | At 3,000 impressions, pause an ad group with under half the other’s CTR; with no signup at $150, stop and keep answering threads instead. |

| Benchmark | Source |
| --- | --- |
| $150 across 2 ad groups for the first test | Our planning number |
| Judge each ad group at 3,000 impressions | Our planning number |
| Promote only a post that earned 10 or more replies on its own | Our planning number |

## Field map
| Our field | Reddit Ads’s field | Notes | Calls |
| --- | --- | --- | --- |
| `Campaign.objective` | `campaign objective` | Picked in Ads Manager: `traffic` sends readers to your page; `leads` bids toward your signup event | [`Campaign.create`](/code/apps/ads/create-campaign), [`Campaign.update`](/code/apps/ads/update-campaign), [`Ad.create`](/code/apps/ads/create-ad) |
| `Campaign.targeting` | `ad group community targeting` | The subreddits, by name | [`Campaign.create`](/code/apps/ads/create-campaign) |
| `Campaign.budget` | `ad group budget` | None. | [`Campaign.create`](/code/apps/ads/create-campaign), [`Campaign.update`](/code/apps/ads/update-campaign), [`Ad.create`](/code/apps/ads/create-ad) |
| `Campaign.startsAt` | `ad group start date and time` | None. | [`Campaign.create`](/code/apps/ads/create-campaign) |
| `Campaign.endsAt` | `ad group end date and time` | None. | [`Campaign.create`](/code/apps/ads/create-campaign), [`Campaign.update`](/code/apps/ads/update-campaign) |
| `Campaign.state` | `campaign and ad group status` | `live` is active, `paused` paused | [`Campaign.update`](/code/apps/ads/update-campaign) |
| `Campaign.bid` | `ad group bid strategy` | `lowest-cost` is automatic bidding; a `costPer` cap is a cost cap on clicks or conversions | [`Campaign.create`](/code/apps/ads/create-campaign), [`Campaign.update`](/code/apps/ads/update-campaign) |
| `Campaign.keywords` | `ad group keyword targeting` | Shows the ad beside conversations that use the words, across subreddits | [`Campaign.create`](/code/apps/ads/create-campaign) |
| `Ad.headline` | `post title` | A promoted post keeps the title it earned replies under | [`Ad.create`](/code/apps/ads/create-ad) |
| `Ad.landingUrl` | `destination URL` | None. | [`Ad.create`](/code/apps/ads/create-ad) |
| `Ad.callToAction` | `call to action button` | Such as Learn More or Sign Up | [`Ad.create`](/code/apps/ads/create-ad) |
| `Ad.media` | `the promoted post’s image or video` | As posted; a new image means a new post | [`Ad.create`](/code/apps/ads/create-ad) |

## What try does here
Returns the campaign and the promoted post as Ads Manager will hold them, with the steps the browser agent would take; no session opens and nothing is created.

## How long a connection lasts
A connection lasts as long as the site keeps your saved session signed in; the platform checks the session before every run.

The platform asks you to reconnect 7 days before it runs out; until you do, a call that needs it refuses with [`needs-reauth`](/code/refusals#needs-reauth).

## Formats
| Site | Format | Size | Limits |
| --- | --- | --- | --- |
| [Reddit](/venues#reddit) | Text or link post | None. | Title 300 characters, which cannot be edited after posting |
| [Reddit](/venues#reddit) | Comment | None. | Text under a post or a comment; it has no title |
| [Reddit](/venues#reddit) | Promoted post | None. | A post already on your account, promoted with the title it earned replies under |

## Plays and strategies
| Kind | Where |
| --- | --- |
| Plays | [Paid social](/plays/paid-social), [Promote winners](/plays/promote-winners) |
| Strategies | [Paid](/strategy/paid) |

## Used by
- **Workflows:** [Ad test setup](/capabilities/run-ads/ad-test-setup)
- **Agent tasks:** [Launch day](/capabilities/earn-first-links/launch-day) · [Message test](/capabilities/run-ads/message-test)

## Reference

| Call | Path | Price |
| --- | --- | --- |
| [`Campaign.create`](/code/apps/ads/create-campaign) | `POST /campaigns/create` | About 1.6¢ a step |
| [`Ad.create`](/code/apps/ads/create-ad) | `POST /ads/create` | About 1.6¢ a step |
| [`Campaign.update`](/code/apps/ads/update-campaign) | `POST /campaigns/update` | About 1.6¢ a step |
| [`Metric.query`](/code/apps/analytics-and-experiments/query) | `POST /metrics/query` | About 1.6¢ a step |