@sprid/cli 0.1.15 → 0.1.16

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/CHANGELOG.md CHANGED
@@ -3,6 +3,15 @@
3
3
  sprid follows semver: a breaking change to a command's arguments, its output
4
4
  shape or its exit codes is a major release.
5
5
 
6
+ ## 0.1.16 - 2026-09-28
7
+
8
+ - `sprid docs revenuecat` explains how to see who buys: send RevenueCat's
9
+ purchase events to the analytics or attribution tool you already use, under
10
+ the same user id. The key's permissions are unchanged.
11
+ - `sprid docs meta-ads` says Instagram posts can only be promoted once the
12
+ Instagram account is linked to the Facebook Page the ad account runs as, and
13
+ how to link it.
14
+
6
15
  ## 0.1.15 - 2026-09-27
7
16
 
8
17
  - `sprid marketing-review save --app <slug> --file <review.json>` saves a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprid/cli",
3
- "version": "0.1.15",
3
+ "version": "0.1.16",
4
4
  "description": "The Sprid command line: connect your app, review results, prepare posts and store screenshots, and release mobile apps.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -608,6 +608,12 @@ export const GUIDES = [
608
608
  "kind": "detail",
609
609
  "markdown": "Connect the services that record the other sales. Sprid withholds a combined total when RevenueCat may already include the same Stripe or Paddle sales, or when currencies or definitions differ. RevenueCat Web Billing and your own Stripe are separate merchant accounts, so they never overlap."
610
610
  },
611
+ {
612
+ "id": "see-who-buys",
613
+ "title": "See who buys",
614
+ "kind": "detail",
615
+ "markdown": "This key tells Sprid how much you sold, split by country, store, product and, when the app sends attribution to RevenueCat, by campaign. It cannot tell which visitor or user became a buyer. More permissions on this key would not change that: RevenueCat’s API reads customers one at a time.\n\nTo see who buys, send RevenueCat’s purchase events to the tool that already knows your users, under the same user id:\n\n1. In the app, give RevenueCat the id your analytics tool uses. Either log the user in with it (`Purchases.logIn`), or set the attribute the integration’s own RevenueCat page names.\n2. In RevenueCat, open **Integrations** and turn on the one you use: Amplitude, Mixpanel, PostHog, Segment, mParticle, Firebase (which reaches Google Analytics), or an attribution provider such as AppsFlyer or Adjust. For anything else, use a webhook or a scheduled export to your warehouse.\n3. Ask the question in that tool: which sources, pages or onboarding steps come before a purchase.\n\nCookieless analytics such as Plausible count visits without knowing who made them, so there is no user to match. Their UTM sources still line up with RevenueCat’s campaign breakdown as totals."
616
+ },
611
617
  {
612
618
  "id": "if-it-fails",
613
619
  "title": "If it fails",
@@ -627,8 +633,8 @@ export const GUIDES = [
627
633
  "markdown": "Setup and live reads checked 2026-09-09.\n\n- [RevenueCat API keys](https://www.revenuecat.com/docs/projects/authentication)\n- [API V2 reference](https://www.revenuecat.com/docs/api-v2)"
628
634
  }
629
635
  ],
630
- "markdown": "# RevenueCat\n\n**What Sprid does with this:** See subscription revenue and how it changes over time.\n\n## You need\n\n**Admin** access to the RevenueCat project, to create a dedicated **V2 secret API key**. The app’s public key and V1 keys do not work.\n\n## Click path (app.revenuecat.com)\n\n1. Select your project → **API keys → Secret API keys → New secret API key**.\n2. Name it `Sprid analytics` and select **V2**.\n3. **Charts metrics permissions**: set **Overview Configuration Access Level** and **Charts Configuration Access Level** to **Read only**.\n4. **Project configuration permissions**: set **Apps Configuration Access Level** to **Read only**. Leave everything else at **No access**.\n5. Click **Generate**. Use a separate key per app.\n6. Copy the key and leave it on your clipboard.\n\n## Project id\n\n**Project settings → General → Project ID**, such as `proj1ab2c3d4`. Not the shorter id in the dashboard address.\n\n## Then run\n\n```sh\nsprid connect revenuecat --app myapp --key-from-clipboard --project proj1ab2c3d4\n```\n\nUse your own app slug and project id. Add `--workspace <slug>` if needed. Keep the key out of chat.\n\nSprid reads the key from your clipboard, saves it and clears the clipboard, so it never shows on screen or lands in a file. Working with an agent? Tell it the key is copied and it runs this for you. Typing it yourself, copy the key last: paste the command into your terminal first, then copy the key, then press Enter. If the clipboard still holds the command, Sprid refuses it; copy the key and run it again. Without clipboard access (a remote shell), save the key to a file and pass `--key <file>` instead.\n\n## How to check it worked\n\nAsk your agent: “Check that Sprid can read this app’s RevenueCat overview and daily revenue history. Report any missing dates.” A saved key alone does not confirm access. The overview can work while history does not; missing dates are not zero sales.\n\n## If you also sell on the web\n\nConnect the services that record the other sales. Sprid withholds a combined total when RevenueCat may already include the same Stripe or Paddle sales, or when currencies or definitions differ. RevenueCat Web Billing and your own Stripe are separate merchant accounts, so they never overlap.\n\n## If it fails\n\n- **Key rejected:** check it is an active V2 secret key for this project.\n- **Access denied or history missing:** open the key’s **More → Edit**, check all three Read only settings, then **Submit**. No new key needed.\n- **Project not found:** copy the full Project ID from **Project settings → General**. Key and id must belong to the same project.\n- **Too many requests:** retry later. Another key will not help.\n\n## Investigate with this connection\n\nReads `chart_options`, `chart` and `subscriptions` for the pinned project. Read `chart_options` before picking dimensions, filters or resolution, and keep the returned units. `subscriptions` also needs `customer_information:subscriptions:read` and defaults to production; ask for sandbox to see test purchases.\n\n```sh\nsprid marketing-review capabilities --app <slug> --source revenuecat --json\n```\n\nSee [connected queries](https://sprid.studio/docs/queries).\n\n## Sources and verification\n\nSetup and live reads checked 2026-09-09.\n\n- [RevenueCat API keys](https://www.revenuecat.com/docs/projects/authentication)\n- [API V2 reference](https://www.revenuecat.com/docs/api-v2)\n",
631
- "revision": "318e11fbdfcb6dec"
636
+ "markdown": "# RevenueCat\n\n**What Sprid does with this:** See subscription revenue and how it changes over time.\n\n## You need\n\n**Admin** access to the RevenueCat project, to create a dedicated **V2 secret API key**. The app’s public key and V1 keys do not work.\n\n## Click path (app.revenuecat.com)\n\n1. Select your project → **API keys → Secret API keys → New secret API key**.\n2. Name it `Sprid analytics` and select **V2**.\n3. **Charts metrics permissions**: set **Overview Configuration Access Level** and **Charts Configuration Access Level** to **Read only**.\n4. **Project configuration permissions**: set **Apps Configuration Access Level** to **Read only**. Leave everything else at **No access**.\n5. Click **Generate**. Use a separate key per app.\n6. Copy the key and leave it on your clipboard.\n\n## Project id\n\n**Project settings → General → Project ID**, such as `proj1ab2c3d4`. Not the shorter id in the dashboard address.\n\n## Then run\n\n```sh\nsprid connect revenuecat --app myapp --key-from-clipboard --project proj1ab2c3d4\n```\n\nUse your own app slug and project id. Add `--workspace <slug>` if needed. Keep the key out of chat.\n\nSprid reads the key from your clipboard, saves it and clears the clipboard, so it never shows on screen or lands in a file. Working with an agent? Tell it the key is copied and it runs this for you. Typing it yourself, copy the key last: paste the command into your terminal first, then copy the key, then press Enter. If the clipboard still holds the command, Sprid refuses it; copy the key and run it again. Without clipboard access (a remote shell), save the key to a file and pass `--key <file>` instead.\n\n## How to check it worked\n\nAsk your agent: “Check that Sprid can read this app’s RevenueCat overview and daily revenue history. Report any missing dates.” A saved key alone does not confirm access. The overview can work while history does not; missing dates are not zero sales.\n\n## If you also sell on the web\n\nConnect the services that record the other sales. Sprid withholds a combined total when RevenueCat may already include the same Stripe or Paddle sales, or when currencies or definitions differ. RevenueCat Web Billing and your own Stripe are separate merchant accounts, so they never overlap.\n\n## See who buys\n\nThis key tells Sprid how much you sold, split by country, store, product and, when the app sends attribution to RevenueCat, by campaign. It cannot tell which visitor or user became a buyer. More permissions on this key would not change that: RevenueCat’s API reads customers one at a time.\n\nTo see who buys, send RevenueCat’s purchase events to the tool that already knows your users, under the same user id:\n\n1. In the app, give RevenueCat the id your analytics tool uses. Either log the user in with it (`Purchases.logIn`), or set the attribute the integration’s own RevenueCat page names.\n2. In RevenueCat, open **Integrations** and turn on the one you use: Amplitude, Mixpanel, PostHog, Segment, mParticle, Firebase (which reaches Google Analytics), or an attribution provider such as AppsFlyer or Adjust. For anything else, use a webhook or a scheduled export to your warehouse.\n3. Ask the question in that tool: which sources, pages or onboarding steps come before a purchase.\n\nCookieless analytics such as Plausible count visits without knowing who made them, so there is no user to match. Their UTM sources still line up with RevenueCat’s campaign breakdown as totals.\n\n## If it fails\n\n- **Key rejected:** check it is an active V2 secret key for this project.\n- **Access denied or history missing:** open the key’s **More → Edit**, check all three Read only settings, then **Submit**. No new key needed.\n- **Project not found:** copy the full Project ID from **Project settings → General**. Key and id must belong to the same project.\n- **Too many requests:** retry later. Another key will not help.\n\n## Investigate with this connection\n\nReads `chart_options`, `chart` and `subscriptions` for the pinned project. Read `chart_options` before picking dimensions, filters or resolution, and keep the returned units. `subscriptions` also needs `customer_information:subscriptions:read` and defaults to production; ask for sandbox to see test purchases.\n\n```sh\nsprid marketing-review capabilities --app <slug> --source revenuecat --json\n```\n\nSee [connected queries](https://sprid.studio/docs/queries).\n\n## Sources and verification\n\nSetup and live reads checked 2026-09-09.\n\n- [RevenueCat API keys](https://www.revenuecat.com/docs/projects/authentication)\n- [API V2 reference](https://www.revenuecat.com/docs/api-v2)\n",
637
+ "revision": "cddafbea362019dc"
632
638
  },
633
639
  {
634
640
  "id": "stripe",
@@ -989,7 +995,7 @@ export const GUIDES = [
989
995
  "id": "you-need",
990
996
  "title": "You need",
991
997
  "kind": "requirements",
992
- "markdown": "- An Instagram **Business** or **Creator** account. A Facebook Page is optional. No account yet? Start with [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- Your phone for any two-factor prompt.\n\nTo switch a personal account: profile → **≡ → Settings and activity → For professionals → Account type and tools → Switch to professional account** → pick a category → **Creator** or **Business**. You can skip linking a Facebook Page."
998
+ "markdown": "- An Instagram **Business** or **Creator** account. A Facebook Page is optional for publishing. To promote Instagram posts as ads, link the account to the Page your [Meta Ads](https://sprid.studio/docs/connect/meta-ads) connection uses. No account yet? Start with [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- Your phone for any two-factor prompt.\n\nTo switch a personal account: profile → **≡ → Settings and activity → For professionals → Account type and tools → Switch to professional account** → pick a category → **Creator** or **Business**. You can skip linking a Facebook Page."
993
999
  },
994
1000
  {
995
1001
  "id": "then-run",
@@ -1028,8 +1034,8 @@ export const GUIDES = [
1028
1034
  "markdown": "- [Instagram API with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/)\n- [Business Login for Instagram](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login)\n- [Permission descriptions and App Review requirement](https://developers.facebook.com/docs/permissions)\n- [App modes](https://developers.facebook.com/docs/development/build-and-test/app-modes)\n- [Switch to a professional account](https://creatorsupport.creatoriq.com/hc/en-us/articles/13578083261709-How-do-I-switch-from-a-Personal-to-a-Professional-Instagram-account)"
1029
1035
  }
1030
1036
  ],
1031
- "markdown": "# Instagram\n\n**What Sprid does with this:** Publish approved posts to Instagram and see how they perform.\n\n## You need\n\n- An Instagram **Business** or **Creator** account. A Facebook Page is optional. No account yet? Start with [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- Your phone for any two-factor prompt.\n\nTo switch a personal account: profile → **≡ → Settings and activity → For professionals → Account type and tools → Switch to professional account** → pick a category → **Creator** or **Business**. You can skip linking a Facebook Page.\n\n## Then run\n\n```\nsprid connect instagram --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug, or use **Settings → Channels → Connect Instagram** in Sprid. In an agent-controlled browser, add `--no-browser` and open the returned link in the session for the intended account. Keep that link private.\n\n## Click path (the connect)\n\n1. Sign in to the Instagram account you want. If another account is signed in, sign out first.\n2. Check the handle in the consent dialog and leave the requested permissions enabled.\n3. Click **Allow** to return to Sprid.\n\n## How to check it worked\n\nRun `sprid status` and check that Instagram shows the right handle. Before scheduling a batch, publish one reviewed post and check it on Instagram.\n\n## If it fails\n\n- **Account not eligible:** switch to Business or Creator, then reconnect.\n- **Already connected elsewhere:** check the handle. If the wrong account was signed in, cancel and restart. Move a connection only if you mean to change its Sprid destination.\n- **Connection expired or permissions missing:** run the connect command again and approve all requested access.\n- **App unavailable, “Invalid Scopes” or a redirect error:** send the error to [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Long-lived token exchange fails after Allow:** authorization did not complete. Send the error text to [Sprid support](mailto:hello@sprid.studio). If Sprid invites your account as a tester, open Instagram **Settings → Website permissions → Apps and websites → Tester Invites**, accept Sprid-IG, then start a fresh connection. The tab may only appear after an invitation. Do not create another Instagram account or your own Meta developer app. `Unsupported request - method type: get` alone does not identify the cause.\n\n## Investigate with this connection\n\nOperations `posts` and `comments`, read from Sprid’s stored publishes, metric snapshots and inbox (no live platform read; missing metrics are unmeasured, not zero).\n\n```sh\nsprid marketing-review capabilities --app <slug> --source instagram --json\n```\n\nSee [connected queries](https://sprid.studio/docs/queries).\n\n## Sources\n\n- [Instagram API with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/)\n- [Business Login for Instagram](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login)\n- [Permission descriptions and App Review requirement](https://developers.facebook.com/docs/permissions)\n- [App modes](https://developers.facebook.com/docs/development/build-and-test/app-modes)\n- [Switch to a professional account](https://creatorsupport.creatoriq.com/hc/en-us/articles/13578083261709-How-do-I-switch-from-a-Personal-to-a-Professional-Instagram-account)\n",
1032
- "revision": "116e5b47d45175e7"
1037
+ "markdown": "# Instagram\n\n**What Sprid does with this:** Publish approved posts to Instagram and see how they perform.\n\n## You need\n\n- An Instagram **Business** or **Creator** account. A Facebook Page is optional for publishing. To promote Instagram posts as ads, link the account to the Page your [Meta Ads](https://sprid.studio/docs/connect/meta-ads) connection uses. No account yet? Start with [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- Your phone for any two-factor prompt.\n\nTo switch a personal account: profile → **≡ → Settings and activity → For professionals → Account type and tools → Switch to professional account** → pick a category → **Creator** or **Business**. You can skip linking a Facebook Page.\n\n## Then run\n\n```\nsprid connect instagram --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug, or use **Settings → Channels → Connect Instagram** in Sprid. In an agent-controlled browser, add `--no-browser` and open the returned link in the session for the intended account. Keep that link private.\n\n## Click path (the connect)\n\n1. Sign in to the Instagram account you want. If another account is signed in, sign out first.\n2. Check the handle in the consent dialog and leave the requested permissions enabled.\n3. Click **Allow** to return to Sprid.\n\n## How to check it worked\n\nRun `sprid status` and check that Instagram shows the right handle. Before scheduling a batch, publish one reviewed post and check it on Instagram.\n\n## If it fails\n\n- **Account not eligible:** switch to Business or Creator, then reconnect.\n- **Already connected elsewhere:** check the handle. If the wrong account was signed in, cancel and restart. Move a connection only if you mean to change its Sprid destination.\n- **Connection expired or permissions missing:** run the connect command again and approve all requested access.\n- **App unavailable, “Invalid Scopes” or a redirect error:** send the error to [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Long-lived token exchange fails after Allow:** authorization did not complete. Send the error text to [Sprid support](mailto:hello@sprid.studio). If Sprid invites your account as a tester, open Instagram **Settings → Website permissions → Apps and websites → Tester Invites**, accept Sprid-IG, then start a fresh connection. The tab may only appear after an invitation. Do not create another Instagram account or your own Meta developer app. `Unsupported request - method type: get` alone does not identify the cause.\n\n## Investigate with this connection\n\nOperations `posts` and `comments`, read from Sprid’s stored publishes, metric snapshots and inbox (no live platform read; missing metrics are unmeasured, not zero).\n\n```sh\nsprid marketing-review capabilities --app <slug> --source instagram --json\n```\n\nSee [connected queries](https://sprid.studio/docs/queries).\n\n## Sources\n\n- [Instagram API with Instagram Login](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/)\n- [Business Login for Instagram](https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/business-login)\n- [Permission descriptions and App Review requirement](https://developers.facebook.com/docs/permissions)\n- [App modes](https://developers.facebook.com/docs/development/build-and-test/app-modes)\n- [Switch to a professional account](https://creatorsupport.creatoriq.com/hc/en-us/articles/13578083261709-How-do-I-switch-from-a-Personal-to-a-Professional-Instagram-account)\n",
1038
+ "revision": "609a953e2195cc7d"
1033
1039
  },
1034
1040
  {
1035
1041
  "id": "tiktok",
@@ -1431,19 +1437,19 @@ export const GUIDES = [
1431
1437
  "id": "you-need",
1432
1438
  "title": "You need",
1433
1439
  "kind": "requirements",
1434
- "markdown": "- A Facebook profile with two-factor authentication turned on. Meta will not let you add ad assets without it.\n- A **business portfolio** at [business.facebook.com](https://business.facebook.com). One per company is enough, even with several apps or brands. See **One portfolio or several** below.\n- A **Facebook Page** for the brand. Ads always run from a Page, including the ones shown on Instagram. To create one, see [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- An **ad account** with a payment method, one per brand.\n- Optional: a **dataset** (formerly Meta Pixel) if you want campaigns that optimise for signups or purchases.\n\nYou do **not** create a Meta developer app or copy a token. You only sign in with Facebook and pick the Page and ad account."
1440
+ "markdown": "- A Facebook profile with two-factor authentication turned on. Meta will not let you add ad assets without it.\n- A **business portfolio** at [business.facebook.com](https://business.facebook.com). One per company is enough, even with several apps or brands. See **One portfolio or several** below.\n- A **Facebook Page** for the brand. Ads always run from a Page, including the ones shown on Instagram. To create one, see [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- To promote **Instagram** posts: the Instagram account **linked to that Page**. Meta runs an Instagram ad through the Page the profile is linked to, so without the link only Facebook posts can be promoted.\n- An **ad account** with a payment method, one per brand.\n- Optional: a **dataset** (formerly Meta Pixel) if you want campaigns that optimise for signups or purchases.\n\nYou do **not** create a Meta developer app or copy a token. You only sign in with Facebook and pick the Page and ad account."
1435
1441
  },
1436
1442
  {
1437
1443
  "id": "set-up-meta-once-before-you-connect",
1438
1444
  "title": "Set up Meta (once, before you connect)",
1439
1445
  "kind": "steps",
1440
- "markdown": "Skip any step you have already done.\n\n1. **Business portfolio.** Go to [business.facebook.com](https://business.facebook.com) and create a business portfolio under your company’s legal name.\n2. **Page.** In the portfolio, open **Settings → Accounts → Pages** and add the brand’s Page. Give yourself access that includes **Ads**.\n3. **Ad account.** Open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully: once the account has spent anything, neither can be changed. Choose the currency of the market you advertise in. Give yourself **Manage campaigns** or full control.\n4. **Payment method.** Open **Billing & payments** for that ad account and add a card. Sprid can connect an account without one, but no campaign can start until it has one.\n5. **Dataset (optional).** Open [Events Manager](https://business.facebook.com/events_manager2) → **Connect data sources → Web**, name it after your domain and copy its **dataset id**. Sprid only needs the id. The events themselves reach it from your site or app, through the Meta Pixel or the Conversions API, and without events a conversion campaign has nothing to optimise for."
1446
+ "markdown": "Skip any step you have already done.\n\n1. **Business portfolio.** Go to [business.facebook.com](https://business.facebook.com) and create a business portfolio under your company’s legal name.\n2. **Page.** In the portfolio, open **Settings → Accounts → Pages** and add the brand’s Page. Give yourself access that includes **Ads**.\n3. **Instagram (to promote Instagram posts).** On the Page, open **Settings → Linked accounts → Instagram** and connect the brand’s Instagram account. It has to be the same account you publish to from Sprid. Sprid reads the link from Meta each time you promote, so you can do this later without reconnecting.\n4. **Ad account.** Open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully: once the account has spent anything, neither can be changed. Choose the currency of the market you advertise in. Give yourself **Manage campaigns** or full control.\n5. **Payment method.** Open **Billing & payments** for that ad account and add a card. Sprid can connect an account without one, but no campaign can start until it has one.\n6. **Dataset (optional).** Open [Events Manager](https://business.facebook.com/events_manager2) → **Connect data sources → Web**, name it after your domain and copy its **dataset id**. Sprid only needs the id. The events themselves reach it from your site or app, through the Meta Pixel or the Conversions API, and without events a conversion campaign has nothing to optimise for."
1441
1447
  },
1442
1448
  {
1443
1449
  "id": "then-run",
1444
1450
  "title": "Then run",
1445
1451
  "kind": "command",
1446
- "markdown": "```sh\nsprid connect meta-ads --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug. Add `--dataset <id>` if you created one in step 5. You can also use **Settings → Accounts → [account] → Meta Ads** in Sprid."
1452
+ "markdown": "```sh\nsprid connect meta-ads --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug. Add `--dataset <id>` if you created one in step 6. You can also use **Settings → Accounts → [account] → Meta Ads** in Sprid."
1447
1453
  },
1448
1454
  {
1449
1455
  "id": "click-path-the-connect",
@@ -1467,17 +1473,17 @@ export const GUIDES = [
1467
1473
  "id": "if-it-fails",
1468
1474
  "title": "If it fails",
1469
1475
  "kind": "troubleshooting",
1470
- "markdown": "- **“No Facebook Pages found”:** the profile you signed in with has no Page access. Check the Page in the portfolio, give yourself access and reconnect.\n- **No ad account to choose, or the wrong ones:** only active ad accounts are listed. Check that the account is not disabled or closed in Ads Manager and that your profile is assigned to it.\n- **“Re-run the connect with --page / --ad-account”:** the profile manages several. Copy the right ids from the message and run the command again with them.\n- **“Already connected to another account”:** that ad account is connected to a different Sprid account. Check you picked the right one; move it only if you mean to.\n- **Campaign refuses to start with a conversion goal:** the connection has no dataset. Reconnect with `--dataset <id>`.\n- **Campaign refuses to start at all:** add a payment method to the ad account (step 4).\n- **“Invalid Scopes”, app unavailable or “URL blocked”:** contact [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Expiring connection in `sprid status`:** Meta’s sign-in lasts about 60 days. Run the connect again."
1476
+ "markdown": "- **“No Facebook Pages found”:** the profile you signed in with has no Page access. Check the Page in the portfolio, give yourself access and reconnect.\n- **No ad account to choose, or the wrong ones:** only active ad accounts are listed. Check that the account is not disabled or closed in Ads Manager and that your profile is assigned to it.\n- **“Re-run the connect with --page / --ad-account”:** the profile manages several. Copy the right ids from the message and run the command again with them.\n- **“Already connected to another account”:** that ad account is connected to a different Sprid account. Check you picked the right one; move it only if you mean to.\n- **Campaign refuses to start with a conversion goal:** the connection has no dataset. Reconnect with `--dataset <id>`.\n- **Campaign refuses to start at all:** add a payment method to the ad account (step 5).\n- **Instagram shows “Not linked” on the Ads page or in Promote:** the Page has no Instagram account linked. Link it (step 3), then press **I’ve linked it**. If the Page is linked to a different Instagram account than the one Sprid publishes to, Meta will only promote that other account’s posts: change the link, or connect the Page that belongs to your Instagram account.\n- **“Invalid Scopes”, app unavailable or “URL blocked”:** contact [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Expiring connection in `sprid status`:** Meta’s sign-in lasts about 60 days. Run the connect again."
1471
1477
  },
1472
1478
  {
1473
1479
  "id": "sources",
1474
1480
  "title": "Sources",
1475
1481
  "kind": "sources",
1476
- "markdown": "- [Create a business portfolio](https://www.facebook.com/business/help/1710077379203657)\n- [Add an ad account to your business portfolio](https://www.facebook.com/business/help/915885887059947)\n- [Ad account limits](https://www.facebook.com/business/help/1026272311098874)\n- [Add a payment method to an ad account](https://www.facebook.com/business/help/132073386867900)\n- [Assign business assets to people](https://www.facebook.com/business/help/325571851329683)\n- [Create a dataset in Events Manager](https://www.facebook.com/business/help/5818684664831465)\n- [About the Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI)"
1482
+ "markdown": "- [Connect a professional Instagram account and a Facebook Page](https://www.facebook.com/business/help/connect-instagram-to-page)\n- [Create a business portfolio](https://www.facebook.com/business/help/1710077379203657)\n- [Add an ad account to your business portfolio](https://www.facebook.com/business/help/915885887059947)\n- [Ad account limits](https://www.facebook.com/business/help/1026272311098874)\n- [Add a payment method to an ad account](https://www.facebook.com/business/help/132073386867900)\n- [Assign business assets to people](https://www.facebook.com/business/help/325571851329683)\n- [Create a dataset in Events Manager](https://www.facebook.com/business/help/5818684664831465)\n- [About the Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI)"
1477
1483
  }
1478
1484
  ],
1479
- "markdown": "# Meta Ads\n\n**What Sprid does with this:** Prepare campaigns in your own Meta ad account, start them only when you confirm, and report what they spent and returned.\n\n## You need\n\n- A Facebook profile with two-factor authentication turned on. Meta will not let you add ad assets without it.\n- A **business portfolio** at [business.facebook.com](https://business.facebook.com). One per company is enough, even with several apps or brands. See **One portfolio or several** below.\n- A **Facebook Page** for the brand. Ads always run from a Page, including the ones shown on Instagram. To create one, see [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- An **ad account** with a payment method, one per brand.\n- Optional: a **dataset** (formerly Meta Pixel) if you want campaigns that optimise for signups or purchases.\n\nYou do **not** create a Meta developer app or copy a token. You only sign in with Facebook and pick the Page and ad account.\n\n## Set up Meta (once, before you connect)\n\nSkip any step you have already done.\n\n1. **Business portfolio.** Go to [business.facebook.com](https://business.facebook.com) and create a business portfolio under your company’s legal name.\n2. **Page.** In the portfolio, open **Settings → Accounts → Pages** and add the brand’s Page. Give yourself access that includes **Ads**.\n3. **Ad account.** Open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully: once the account has spent anything, neither can be changed. Choose the currency of the market you advertise in. Give yourself **Manage campaigns** or full control.\n4. **Payment method.** Open **Billing & payments** for that ad account and add a card. Sprid can connect an account without one, but no campaign can start until it has one.\n5. **Dataset (optional).** Open [Events Manager](https://business.facebook.com/events_manager2) → **Connect data sources → Web**, name it after your domain and copy its **dataset id**. Sprid only needs the id. The events themselves reach it from your site or app, through the Meta Pixel or the Conversions API, and without events a conversion campaign has nothing to optimise for.\n\n## Then run\n\n```sh\nsprid connect meta-ads --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug. Add `--dataset <id>` if you created one in step 5. You can also use **Settings → Accounts → [account] → Meta Ads** in Sprid.\n\n## Click path (the connect)\n\n1. Sign in with the Facebook profile that manages the Page and the ad account.\n2. Leave every requested permission switched on and click **Continue**.\n3. Back in Sprid, pick the **Page** your ads should appear from, then the **ad account**. Each list only appears when there is more than one to choose from.\n4. From the CLI, a profile with several Pages or ad accounts gets a message listing their ids. Run the command again with them:\n\n```sh\nsprid connect meta-ads --account <slug> --page <page id> --ad-account <ad account id> --dataset <dataset id>\n```\n\nWith several brands, connect each Sprid account separately and pick that brand’s own Page and ad account every time.\n\n## Check the connection\n\nRun `sprid status` and check that Meta Ads shows the intended Page name, followed by “(Ads)”.\n\nA campaign Sprid prepares starts **paused**. Nothing is spent until you confirm the start.\n\n## One portfolio or several\n\nKeep one business portfolio for your company and put one Page, one ad account and one dataset per brand inside it.\n\n- **A restriction on an ad account stays on that account.** The other brands keep running.\n- **Separate portfolios isolate less than they appear to.** Meta links portfolios run by the same people and paid with the same card, so a problem on one is often read as a problem on all of them. You also pay for the split: each portfolio has to be verified and set up separately, and a personal profile can only create a couple of them.\n- **What one portfolio risks:** if the portfolio itself is restricted, every brand in it stops at once. If one brand operates in a regulated category (housing, credit, employment, politics) and draws an enforcement action, move that brand to its own portfolio then.\n\nGive each ad account its own payment method where you can, and add a second admin to the portfolio so you are not locked out if your own profile has a problem.\n\n## If it fails\n\n- **“No Facebook Pages found”:** the profile you signed in with has no Page access. Check the Page in the portfolio, give yourself access and reconnect.\n- **No ad account to choose, or the wrong ones:** only active ad accounts are listed. Check that the account is not disabled or closed in Ads Manager and that your profile is assigned to it.\n- **“Re-run the connect with --page / --ad-account”:** the profile manages several. Copy the right ids from the message and run the command again with them.\n- **“Already connected to another account”:** that ad account is connected to a different Sprid account. Check you picked the right one; move it only if you mean to.\n- **Campaign refuses to start with a conversion goal:** the connection has no dataset. Reconnect with `--dataset <id>`.\n- **Campaign refuses to start at all:** add a payment method to the ad account (step 4).\n- **“Invalid Scopes”, app unavailable or “URL blocked”:** contact [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Expiring connection in `sprid status`:** Meta’s sign-in lasts about 60 days. Run the connect again.\n\n## Sources\n\n- [Create a business portfolio](https://www.facebook.com/business/help/1710077379203657)\n- [Add an ad account to your business portfolio](https://www.facebook.com/business/help/915885887059947)\n- [Ad account limits](https://www.facebook.com/business/help/1026272311098874)\n- [Add a payment method to an ad account](https://www.facebook.com/business/help/132073386867900)\n- [Assign business assets to people](https://www.facebook.com/business/help/325571851329683)\n- [Create a dataset in Events Manager](https://www.facebook.com/business/help/5818684664831465)\n- [About the Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI)\n",
1480
- "revision": "ee377cb02a88bda4"
1485
+ "markdown": "# Meta Ads\n\n**What Sprid does with this:** Prepare campaigns in your own Meta ad account, start them only when you confirm, and report what they spent and returned.\n\n## You need\n\n- A Facebook profile with two-factor authentication turned on. Meta will not let you add ad assets without it.\n- A **business portfolio** at [business.facebook.com](https://business.facebook.com). One per company is enough, even with several apps or brands. See **One portfolio or several** below.\n- A **Facebook Page** for the brand. Ads always run from a Page, including the ones shown on Instagram. To create one, see [Create your social accounts](https://sprid.studio/docs/connect/social-accounts).\n- To promote **Instagram** posts: the Instagram account **linked to that Page**. Meta runs an Instagram ad through the Page the profile is linked to, so without the link only Facebook posts can be promoted.\n- An **ad account** with a payment method, one per brand.\n- Optional: a **dataset** (formerly Meta Pixel) if you want campaigns that optimise for signups or purchases.\n\nYou do **not** create a Meta developer app or copy a token. You only sign in with Facebook and pick the Page and ad account.\n\n## Set up Meta (once, before you connect)\n\nSkip any step you have already done.\n\n1. **Business portfolio.** Go to [business.facebook.com](https://business.facebook.com) and create a business portfolio under your company’s legal name.\n2. **Page.** In the portfolio, open **Settings → Accounts → Pages** and add the brand’s Page. Give yourself access that includes **Ads**.\n3. **Instagram (to promote Instagram posts).** On the Page, open **Settings → Linked accounts → Instagram** and connect the brand’s Instagram account. It has to be the same account you publish to from Sprid. Sprid reads the link from Meta each time you promote, so you can do this later without reconnecting.\n4. **Ad account.** Open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully: once the account has spent anything, neither can be changed. Choose the currency of the market you advertise in. Give yourself **Manage campaigns** or full control.\n5. **Payment method.** Open **Billing & payments** for that ad account and add a card. Sprid can connect an account without one, but no campaign can start until it has one.\n6. **Dataset (optional).** Open [Events Manager](https://business.facebook.com/events_manager2) → **Connect data sources → Web**, name it after your domain and copy its **dataset id**. Sprid only needs the id. The events themselves reach it from your site or app, through the Meta Pixel or the Conversions API, and without events a conversion campaign has nothing to optimise for.\n\n## Then run\n\n```sh\nsprid connect meta-ads --account <slug>\n```\n\nReplace `<slug>` with your Sprid account slug. Add `--dataset <id>` if you created one in step 6. You can also use **Settings → Accounts → [account] → Meta Ads** in Sprid.\n\n## Click path (the connect)\n\n1. Sign in with the Facebook profile that manages the Page and the ad account.\n2. Leave every requested permission switched on and click **Continue**.\n3. Back in Sprid, pick the **Page** your ads should appear from, then the **ad account**. Each list only appears when there is more than one to choose from.\n4. From the CLI, a profile with several Pages or ad accounts gets a message listing their ids. Run the command again with them:\n\n```sh\nsprid connect meta-ads --account <slug> --page <page id> --ad-account <ad account id> --dataset <dataset id>\n```\n\nWith several brands, connect each Sprid account separately and pick that brand’s own Page and ad account every time.\n\n## Check the connection\n\nRun `sprid status` and check that Meta Ads shows the intended Page name, followed by “(Ads)”.\n\nA campaign Sprid prepares starts **paused**. Nothing is spent until you confirm the start.\n\n## One portfolio or several\n\nKeep one business portfolio for your company and put one Page, one ad account and one dataset per brand inside it.\n\n- **A restriction on an ad account stays on that account.** The other brands keep running.\n- **Separate portfolios isolate less than they appear to.** Meta links portfolios run by the same people and paid with the same card, so a problem on one is often read as a problem on all of them. You also pay for the split: each portfolio has to be verified and set up separately, and a personal profile can only create a couple of them.\n- **What one portfolio risks:** if the portfolio itself is restricted, every brand in it stops at once. If one brand operates in a regulated category (housing, credit, employment, politics) and draws an enforcement action, move that brand to its own portfolio then.\n\nGive each ad account its own payment method where you can, and add a second admin to the portfolio so you are not locked out if your own profile has a problem.\n\n## If it fails\n\n- **“No Facebook Pages found”:** the profile you signed in with has no Page access. Check the Page in the portfolio, give yourself access and reconnect.\n- **No ad account to choose, or the wrong ones:** only active ad accounts are listed. Check that the account is not disabled or closed in Ads Manager and that your profile is assigned to it.\n- **“Re-run the connect with --page / --ad-account”:** the profile manages several. Copy the right ids from the message and run the command again with them.\n- **“Already connected to another account”:** that ad account is connected to a different Sprid account. Check you picked the right one; move it only if you mean to.\n- **Campaign refuses to start with a conversion goal:** the connection has no dataset. Reconnect with `--dataset <id>`.\n- **Campaign refuses to start at all:** add a payment method to the ad account (step 5).\n- **Instagram shows “Not linked” on the Ads page or in Promote:** the Page has no Instagram account linked. Link it (step 3), then press **I’ve linked it**. If the Page is linked to a different Instagram account than the one Sprid publishes to, Meta will only promote that other account’s posts: change the link, or connect the Page that belongs to your Instagram account.\n- **“Invalid Scopes”, app unavailable or “URL blocked”:** contact [Sprid support](mailto:hello@sprid.studio). Only Sprid can fix these.\n- **Expiring connection in `sprid status`:** Meta’s sign-in lasts about 60 days. Run the connect again.\n\n## Sources\n\n- [Connect a professional Instagram account and a Facebook Page](https://www.facebook.com/business/help/connect-instagram-to-page)\n- [Create a business portfolio](https://www.facebook.com/business/help/1710077379203657)\n- [Add an ad account to your business portfolio](https://www.facebook.com/business/help/915885887059947)\n- [Ad account limits](https://www.facebook.com/business/help/1026272311098874)\n- [Add a payment method to an ad account](https://www.facebook.com/business/help/132073386867900)\n- [Assign business assets to people](https://www.facebook.com/business/help/325571851329683)\n- [Create a dataset in Events Manager](https://www.facebook.com/business/help/5818684664831465)\n- [About the Conversions API](https://www.facebook.com/business/help/AboutConversionsAPI)\n",
1486
+ "revision": "4e3975328ec3a170"
1481
1487
  },
1482
1488
  {
1483
1489
  "id": "google-ads",
@@ -1646,8 +1652,8 @@ export const CONTENT_GUIDES = [
1646
1652
  "title": "Ads: pay to show more people what already worked",
1647
1653
  "summary": "Explains how Sprid thinks about paid ads on Instagram, Facebook, YouTube and TikTok: when to spend, how a promotion runs from draft to result, and which numbers to believe along the way.",
1648
1654
  "url": "https://sprid.studio/docs/ads",
1649
- "markdown": "# Ads: pay to show more people what already worked\n\n**What this guide does:** Explains how Sprid thinks about paid ads on\nInstagram, Facebook, YouTube and TikTok: when to spend, how a promotion runs\nfrom draft to result, and which numbers to believe along the way.\n\nAds don't rescue a post nobody wanted. They amplify, and they amplify\nwhatever you give them, including a weak idea. So the order Sprid follows is\norganic first: publish, see which posts people actually watched and saved, and\nput money behind the one that already beat your normal. That post has passed\nthe hardest test for free.\n\n## What we believe\n\n**Promote proof, not hope.** A post that did twice your median has evidence\nbehind it. A brand-new creative has only an opinion. Start with the post, and\nmake new creatives once you know what the winning one had.\n\n**Nothing spends without you.** Everything Sprid or your agent prepares is\npaused. Exactly one step starts spending, and it waits for your yes, showing\nwhat will run, what it costs a day and for how long. An agent never moves a\nbudget between reads on its own.\n\n**Keep the words, vary the picture.** We read 3,549 live ads across five\nmarkets. Among advertisers running eight or more, the median was 2.9 ads per\nline of copy, and the largest wellness advertiser ran 109 ads on essentially one\nline. The ad library counts placements separately, so the exact ratio overstates,\nbut the shape holds: the people who keep paying hold the copy and change the\ncreative. A new version changes one thing, or the result teaches nothing.\n\n**Give it time to be readable.** Meta's delivery settles after roughly 50\noptimisation events in a week, and Google and TikTok need a similar learning\nperiod. Before that, a result is noise, and the most\ncommon way to waste money on ads is to stop an ad set before it has said\nanything, then decide the idea doesn't work. Sprid says whether a result is\nreadable before it says whether it worked.\n\n**Judge by what happens in your product.** Cost per install or subscriber comes\nfirst and impressions come last, because the order a report puts numbers in is\nthe order people believe them in. When your app reports who became a paying\ncustomer, that outranks anything the platform can see.\n\n## Two ways to start\n\n**Promote a post.** Pick a post already live, set a daily budget and an end\ndate, and confirm. The ad runs only where that post lives, through the network\nbehind it:\n\n| Post live on | Runs as | Paid by |\n|---|---|---|\n| Instagram | a Meta ad on Instagram only | your Meta ad account |\n| Facebook | a Meta ad on Facebook only | your Meta ad account |\n| YouTube | a Google Ads video campaign (YouTube, Shorts, Discover, Gmail) | your Google Ads account |\n| TikTok | a Spark Ad on TikTok | your TikTok ad account |\n\nSprid checks the ad account can pay before you choose a budget, the network\nreviews the ad, and you get an email when it goes live, is rejected (with the\nnetwork's reason) or ends (with what the money bought). The budget and end date\ncan change while it runs, from Sprid. A TikTok post also needs the creator's\npermission for that one post: a code the TikTok app makes under the post's Ad\nsettings, pasted into Sprid.\n\n**Run a test.** For finding out what to say, not just saying it louder. Tests\nrun on Meta. Every\ncreative is built from a named shape, such as the screen that shows the app's\nverdict about the reader, two columns where the reader does the arithmetic, or\none sourced number. The shape is what makes a result transferable: \"showing the\nverdict beat listing features\" is something you can build again, \"ad 7 beat\nad 3\" is not.\n\n## The checks before money moves\n\n- **The copy check.** Banned words, your own never-say list, invented urgency,\n and openings that name an identity (\"for anxious people\") instead of a moment\n (\"you reread the message four times\"). Warnings pass, errors block the launch.\n- **Regulated categories.** Housing, credit, employment and political ads must\n be declared. An undeclared one isn't quietly rejected, it's pulled with the\n ad account attached. Anything about where people live, what they can borrow or\n who gets hired counts, even when the product doesn't look like it.\n- **The payment method**, before a budget is chosen rather than after Meta has\n accepted the campaign and refused the ad.\n\n## Reading the result\n\nAsk for an ad set's verdict once a week and it answers three questions: did it\nwork, why, and what next.\nWhen a test ends, it writes down what the hypothesis was, what happened and\nwhich shape carried it, so the next test starts from that instead of from zero.\nA losing set is data: close it and say what it ruled out.\n\nTwo rules for the numbers. A campaign's totals and its ad sets' totals are\nseparate readings of the same money, never added together. And a period that\nends today and one that ended last week are two different readings, so every\nnumber says which window it covers.\n\n## What competitors can and can't tell you\n\nMeta's Ad Library shows every active ad: the creative, the copy and the date it\nstarted. It shows no spend, no clicks and no results. Days live means somebody\nkeeps paying, not that it works, so a competitor's ad is \"longest-running\",\nnever \"best-performing\". Sprid's scout research reads the library for your own\nmarket, which is where the shapes above came from.\n\n## You need\n\n- An ad account with a card on it, connected to Sprid, for the network behind\n the post: [Meta Ads](https://sprid.studio/docs/connect/meta-ads) for\n Instagram and Facebook, [Google Ads](https://sprid.studio/docs/connect/google-ads)\n for YouTube, [TikTok Ads](https://sprid.studio/docs/connect/tiktok-ads) for\n TikTok.\n- A published post to promote, or, on Meta, an image or video to build a\n creative from.\n- For an agent to launch anything, a token that holds the `ads:spend`\n permission. It's granted deliberately, on a token made for it.\n",
1650
- "revision": "a6578de65ac0525b"
1655
+ "markdown": "# Ads: pay to show more people what already worked\n\n**What this guide does:** Explains how Sprid thinks about paid ads on\nInstagram, Facebook, YouTube and TikTok: when to spend, how a promotion runs\nfrom draft to result, and which numbers to believe along the way.\n\nAds don't rescue a post nobody wanted. They amplify, and they amplify\nwhatever you give them, including a weak idea. So the order Sprid follows is\norganic first: publish, see which posts people actually watched and saved, and\nput money behind the one that already beat your normal. That post has passed\nthe hardest test for free.\n\n## What we believe\n\n**Promote proof, not hope.** A post that did twice your median has evidence\nbehind it. A brand-new creative has only an opinion. Start with the post, and\nmake new creatives once you know what the winning one had.\n\n**Nothing spends without you.** Everything Sprid or your agent prepares is\npaused. Exactly one step starts spending, and it waits for your yes, showing\nwhat will run, what it costs a day and for how long. An agent never moves a\nbudget between reads on its own.\n\n**Keep the words, vary the picture.** We read 3,549 live ads across five\nmarkets. Among advertisers running eight or more, the median was 2.9 ads per\nline of copy, and the largest wellness advertiser ran 109 ads on essentially one\nline. The ad library counts placements separately, so the exact ratio overstates,\nbut the shape holds: the people who keep paying hold the copy and change the\ncreative. A new version changes one thing, or the result teaches nothing.\n\n**Give it time to be readable.** Meta's delivery settles after roughly 50\noptimisation events in a week, and Google and TikTok need a similar learning\nperiod. Before that, a result is noise, and the most\ncommon way to waste money on ads is to stop an ad set before it has said\nanything, then decide the idea doesn't work. Sprid says whether a result is\nreadable before it says whether it worked.\n\n**Judge by what happens in your product.** Cost per install or subscriber comes\nfirst and impressions come last, because the order a report puts numbers in is\nthe order people believe them in. When your app reports who became a paying\ncustomer, that outranks anything the platform can see.\n\n## Two ways to start\n\n**Promote a post.** Pick a post already live, set a daily budget and an end\ndate, and confirm. The ad runs only where that post lives, through the network\nbehind it:\n\n| Post live on | Runs as | Paid by |\n|---|---|---|\n| Instagram | a Meta ad on Instagram only | your Meta ad account |\n| Facebook | a Meta ad on Facebook only | your Meta ad account |\n| YouTube | a Google Ads video campaign (YouTube, Shorts, Discover, Gmail) | your Google Ads account |\n| TikTok | a Spark Ad on TikTok | your TikTok ad account |\n\nInstagram needs one more thing: the Instagram account has to be linked to the\nFacebook Page your Meta ad account runs as, because that is how Meta runs an\nInstagram ad. Until it is, the Ads page shows Instagram as **Not linked**, and\ntapping it says what to do.\n\nSprid checks the ad account can pay before you choose a budget, the network\nreviews the ad, and you get an email when it goes live, is rejected (with the\nnetwork's reason) or ends (with what the money bought). The budget and end date\ncan change while it runs, from Sprid. A TikTok post also needs the creator's\npermission for that one post: a code the TikTok app makes under the post's Ad\nsettings, pasted into Sprid.\n\n**Run a test.** For finding out what to say, not just saying it louder. Tests\nrun on Meta. Every\ncreative is built from a named shape, such as the screen that shows the app's\nverdict about the reader, two columns where the reader does the arithmetic, or\none sourced number. The shape is what makes a result transferable: \"showing the\nverdict beat listing features\" is something you can build again, \"ad 7 beat\nad 3\" is not.\n\n## The checks before money moves\n\n- **The copy check.** Banned words, your own never-say list, invented urgency,\n and openings that name an identity (\"for anxious people\") instead of a moment\n (\"you reread the message four times\"). Warnings pass, errors block the launch.\n- **Regulated categories.** Housing, credit, employment and political ads must\n be declared. An undeclared one isn't quietly rejected, it's pulled with the\n ad account attached. Anything about where people live, what they can borrow or\n who gets hired counts, even when the product doesn't look like it.\n- **The payment method**, before a budget is chosen rather than after Meta has\n accepted the campaign and refused the ad.\n\n## Reading the result\n\nAsk for an ad set's verdict once a week and it answers three questions: did it\nwork, why, and what next.\nWhen a test ends, it writes down what the hypothesis was, what happened and\nwhich shape carried it, so the next test starts from that instead of from zero.\nA losing set is data: close it and say what it ruled out.\n\nTwo rules for the numbers. A campaign's totals and its ad sets' totals are\nseparate readings of the same money, never added together. And a period that\nends today and one that ended last week are two different readings, so every\nnumber says which window it covers.\n\n## What competitors can and can't tell you\n\nMeta's Ad Library shows every active ad: the creative, the copy and the date it\nstarted. It shows no spend, no clicks and no results. Days live means somebody\nkeeps paying, not that it works, so a competitor's ad is \"longest-running\",\nnever \"best-performing\". Sprid's scout research reads the library for your own\nmarket, which is where the shapes above came from.\n\n## You need\n\n- An ad account with a card on it, connected to Sprid, for the network behind\n the post: [Meta Ads](https://sprid.studio/docs/connect/meta-ads) for\n Instagram and Facebook, [Google Ads](https://sprid.studio/docs/connect/google-ads)\n for YouTube, [TikTok Ads](https://sprid.studio/docs/connect/tiktok-ads) for\n TikTok.\n- A published post to promote, or, on Meta, an image or video to build a\n creative from.\n- For an agent to launch anything, a token that holds the `ads:spend`\n permission. It's granted deliberately, on a token made for it.\n",
1656
+ "revision": "4b66554216a5efed"
1651
1657
  },
1652
1658
  {
1653
1659
  "id": "reel-first-seconds",