@sprid/cli 1.2.4 → 1.2.6
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 +10 -0
- package/package.json +1 -1
- package/src/docs/guides.generated.mjs +21 -13
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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
|
+
## 1.2.6 - 2026-10-14
|
|
7
|
+
|
|
8
|
+
- Conversion campaign guidance covers preflight checks, attribution, placement assets and app approval. Meta connection guidance covers sharing an ad account across apps, shared spending limits and removing access.
|
|
9
|
+
|
|
10
|
+
- The chat guide provides an app fallback when a connector does not expose account creation.
|
|
11
|
+
|
|
12
|
+
## 1.2.5 - 2026-10-12
|
|
13
|
+
|
|
14
|
+
- `sprid docs chat` carries the updated chat guide: an agent creates a missing content account itself with `create_content_account`, and asks whether the app has users before offering analytics and revenue connections.
|
|
15
|
+
|
|
6
16
|
## 1.2.4 - 2026-10-11
|
|
7
17
|
|
|
8
18
|
- `sprid post sync` no longer reports a post as synced when its new media never reached Sprid. A file rebuilt since `register`, or a post whose checks are not passing, is now listed as not synced with the step that fixes it, and the command exits 1. `draft` also reads each slide back and says so when Sprid is still holding the old file.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sprid/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
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",
|
|
@@ -1451,13 +1451,13 @@ export const GUIDES = [
|
|
|
1451
1451
|
"id": "you-need",
|
|
1452
1452
|
"title": "You need",
|
|
1453
1453
|
"kind": "requirements",
|
|
1454
|
-
"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
|
|
1454
|
+
"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. Several apps in the same Sprid workspace can share it.\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."
|
|
1455
1455
|
},
|
|
1456
1456
|
{
|
|
1457
1457
|
"id": "set-up-meta-once-before-you-connect",
|
|
1458
1458
|
"title": "Set up Meta (once, before you connect)",
|
|
1459
1459
|
"kind": "steps",
|
|
1460
|
-
"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.**
|
|
1460
|
+
"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.** Use an existing ad account, or open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully. Changing them creates a new ad account and closes the old one, stopping its ads. 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\nFor campaigns that optimise for signups or purchases, three more:\n\n7. **Conversions API token** (if your server sends the events). Open the dataset → **Settings → Conversions API** and go through Meta's setup guide to the end. The events and fields you tick there only shape its instructions, not what your server may send. Generate the access token there and store it on your server. Sprid never needs it.\n8. **Dataset settings.** Review Meta’s settings and any restrictions shown for this dataset. A server-only Conversions API integration can send events without browser pixel code.\n9. **Advertising settings.** Review any optional AI tests that change your destination or its presentation. Creative opt-outs cannot verify account-level tests. Define engaged audiences and existing customers before using audience-segment reports."
|
|
1461
1461
|
},
|
|
1462
1462
|
{
|
|
1463
1463
|
"id": "then-run",
|
|
@@ -1469,35 +1469,35 @@ export const GUIDES = [
|
|
|
1469
1469
|
"id": "click-path-the-connect",
|
|
1470
1470
|
"title": "Click path (the connect)",
|
|
1471
1471
|
"kind": "steps",
|
|
1472
|
-
"markdown": "1. 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
|
|
1472
|
+
"markdown": "1. 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 apps, connect each Sprid account separately. Pick that app’s Page and dataset each time; you can select the same ad account for apps in the same workspace. Their campaigns and conversion lists stay separate."
|
|
1473
1473
|
},
|
|
1474
1474
|
{
|
|
1475
1475
|
"id": "check-the-connection",
|
|
1476
1476
|
"title": "Check the connection",
|
|
1477
1477
|
"kind": "verify",
|
|
1478
|
-
"markdown": "Run `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."
|
|
1478
|
+
"markdown": "Run `sprid status` and check that Meta Ads shows the intended Page name, followed by “(Ads)”.\n\nFor conversion delivery, complete the intended action and confirm its exact event name in Events Manager. An API response such as `{\"events_received\":1}` only acknowledges the request; it does not prove the chosen event arrived. Then ask your agent to run `dataset_health` for that event. A dataset ID alone cannot pass the conversion launch check. Follow [Run your first Meta conversion campaign](https://sprid.studio/docs/meta-conversions#prove-the-conversion-signal) for testing and custom conversions.\n\nA campaign Sprid prepares starts **paused**. Nothing is spent until you confirm the start."
|
|
1479
1479
|
},
|
|
1480
1480
|
{
|
|
1481
1481
|
"id": "one-portfolio-or-several",
|
|
1482
1482
|
"title": "One portfolio or several",
|
|
1483
1483
|
"kind": "detail",
|
|
1484
|
-
"markdown": "Keep one business portfolio for your company and
|
|
1484
|
+
"markdown": "Keep one business portfolio for your company. Use a Page and dataset for each app. You can share one ad account across apps in the same Sprid workspace, or use separate ad accounts if Meta allows them and you want separate billing.\n\nA shared ad account uses one billing currency. Its payment and account status affect every app advertising through it. Check the currency before choosing budgets.\n\nIn Sprid, open **Ad settings → Shared Meta limits** on any connected account. A workspace owner or admin can set the combined daily budget and monthly spend-and-commitment limit. These limits cover campaigns managed through Sprid. Meta can vary actual daily spend, and changes made directly in Ads Manager can exceed these limits. Lowering a limit blocks new commitments; it does not pause running ads.\n\n**Disconnect** removes only the selected Sprid connection. **Remove access** first lists every connection using the same Meta authorization, then asks you to confirm in Sprid. Removing access stops Sprid from managing those connections; running ads remain on Meta. Reconnect older connections if Sprid cannot identify who authorized them."
|
|
1485
1485
|
},
|
|
1486
1486
|
{
|
|
1487
1487
|
"id": "if-it-fails",
|
|
1488
1488
|
"title": "If it fails",
|
|
1489
1489
|
"kind": "troubleshooting",
|
|
1490
|
-
"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”:**
|
|
1490
|
+
"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”:** check the workspace. Sharing a Meta ad account is supported within one workspace. Social publishing channels still belong to one Sprid account at a time.\n- **Campaign refuses to start with a conversion goal:** inspect the readiness reason. Connect the correct dataset, send a real event, or confirm a recent fire of the selected custom conversion. [The conversion guide](https://sprid.studio/docs/meta-conversions#if-it-fails) covers each repair.\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."
|
|
1491
1491
|
},
|
|
1492
1492
|
{
|
|
1493
1493
|
"id": "sources",
|
|
1494
1494
|
"title": "Sources",
|
|
1495
1495
|
"kind": "sources",
|
|
1496
|
-
"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)"
|
|
1496
|
+
"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)\n\n- [Ad account currency and time zone changes](https://www.facebook.com/business/help/291404291014138)"
|
|
1497
1497
|
}
|
|
1498
1498
|
],
|
|
1499
|
-
"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
|
|
1500
|
-
"revision": "
|
|
1499
|
+
"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. Several apps in the same Sprid workspace can share it.\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.** Use an existing ad account, or open **Settings → Accounts → Ad accounts → Add → Create a new ad account**. Pick the **currency** and **time zone** carefully. Changing them creates a new ad account and closes the old one, stopping its ads. 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\nFor campaigns that optimise for signups or purchases, three more:\n\n7. **Conversions API token** (if your server sends the events). Open the dataset → **Settings → Conversions API** and go through Meta's setup guide to the end. The events and fields you tick there only shape its instructions, not what your server may send. Generate the access token there and store it on your server. Sprid never needs it.\n8. **Dataset settings.** Review Meta’s settings and any restrictions shown for this dataset. A server-only Conversions API integration can send events without browser pixel code.\n9. **Advertising settings.** Review any optional AI tests that change your destination or its presentation. Creative opt-outs cannot verify account-level tests. Define engaged audiences and existing customers before using audience-segment reports.\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 apps, connect each Sprid account separately. Pick that app’s Page and dataset each time; you can select the same ad account for apps in the same workspace. Their campaigns and conversion lists stay separate.\n\n## Check the connection\n\nRun `sprid status` and check that Meta Ads shows the intended Page name, followed by “(Ads)”.\n\nFor conversion delivery, complete the intended action and confirm its exact event name in Events Manager. An API response such as `{\"events_received\":1}` only acknowledges the request; it does not prove the chosen event arrived. Then ask your agent to run `dataset_health` for that event. A dataset ID alone cannot pass the conversion launch check. Follow [Run your first Meta conversion campaign](https://sprid.studio/docs/meta-conversions#prove-the-conversion-signal) for testing and custom conversions.\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. Use a Page and dataset for each app. You can share one ad account across apps in the same Sprid workspace, or use separate ad accounts if Meta allows them and you want separate billing.\n\nA shared ad account uses one billing currency. Its payment and account status affect every app advertising through it. Check the currency before choosing budgets.\n\nIn Sprid, open **Ad settings → Shared Meta limits** on any connected account. A workspace owner or admin can set the combined daily budget and monthly spend-and-commitment limit. These limits cover campaigns managed through Sprid. Meta can vary actual daily spend, and changes made directly in Ads Manager can exceed these limits. Lowering a limit blocks new commitments; it does not pause running ads.\n\n**Disconnect** removes only the selected Sprid connection. **Remove access** first lists every connection using the same Meta authorization, then asks you to confirm in Sprid. Removing access stops Sprid from managing those connections; running ads remain on Meta. Reconnect older connections if Sprid cannot identify who authorized them.\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”:** check the workspace. Sharing a Meta ad account is supported within one workspace. Social publishing channels still belong to one Sprid account at a time.\n- **Campaign refuses to start with a conversion goal:** inspect the readiness reason. Connect the correct dataset, send a real event, or confirm a recent fire of the selected custom conversion. [The conversion guide](https://sprid.studio/docs/meta-conversions#if-it-fails) covers each repair.\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\n- [Ad account currency and time zone changes](https://www.facebook.com/business/help/291404291014138)\n",
|
|
1500
|
+
"revision": "a6934ad7446d8f53"
|
|
1501
1501
|
},
|
|
1502
1502
|
{
|
|
1503
1503
|
"id": "google-ads",
|
|
@@ -1665,8 +1665,8 @@ export const CONTENT_GUIDES = [
|
|
|
1665
1665
|
"title": "Use Sprid in chat",
|
|
1666
1666
|
"summary": "Take an app from setup to a reviewed post and confirmed delivery using only your chat app and a browser. No CLI or installed skills needed.",
|
|
1667
1667
|
"url": "https://sprid.studio/docs/chat",
|
|
1668
|
-
"markdown": "# Use Sprid in chat\n\n**What this guide does:** Take an app from setup to a reviewed post and confirmed delivery using only your chat app and a browser. No CLI or installed skills needed.\n\nYou tell the agent what you want; it handles the tool calls below. The tool names are here so the agent knows the order. Setup should only ask for the connection the current task needs.\n\n## Connect Sprid\n\nChoose your chat at `https://sprid.studio/start#chat` and follow its steps. Your chat may call this an app, connector or integration. The address is `https://api.sprid.studio/api/mcp?surface=core`. Sign in to Sprid and authorize the right workspace.\n\nAgent:
|
|
1669
|
-
"revision": "
|
|
1668
|
+
"markdown": "# Use Sprid in chat\n\n**What this guide does:** Take an app from setup to a reviewed post and confirmed delivery using only your chat app and a browser. No CLI or installed skills needed.\n\nYou tell the agent what you want; it handles the tool calls below. The tool names are here so the agent knows the order. Setup should only ask for the connection the current task needs.\n\n## Connect Sprid\n\nChoose your chat at `https://sprid.studio/start#chat` and follow its steps. Your chat may call this an app, connector or integration. The address is `https://api.sprid.studio/api/mcp?surface=core`. Sign in to Sprid and authorize the right workspace.\n\nAgent: once the app exists, start with `get_marketing_plan` and reuse its prepared work and next step rather than starting over. Discovery can start from a website or store URL, with no social account.\n\n## Pick the app and account\n\nAgent: call `get_capabilities`, then `list_apps` and `list_accounts`, and reuse what exists. If the app is missing, get its description or website/store URL, confirm it and create it with `upsert_app_profile`. A content account owns voice and media; a channel is one exact social destination. Never pick a handle just because it is first in a list. If the app has no account, ask what to call it. Use `create_content_account` when your connector exposes it. If that tool is unavailable, open `https://app.sprid.studio/settings/accounts/new?workspaceId=<workspace-id>&app=<app-id>` with the selected app’s workspace and app IDs filled in. Ask the person to confirm that app and create the account, then read `list_accounts` again.\n\nThen ask whether the app has users yet. If it does, offer the analytics and revenue connections `next_actions` lists first: each link opens Sprid’s secure form, and the first recommendation then reads real numbers. If it has none yet, go on to the first post; connecting stays optional.\n\n## Connect a destination or data source\n\n- **Social channel:** `get_documentation` with the platform name, then `connect_channel`. The person opens the returned link and approves in the browser; `channel_status` confirms the saved result.\n- **Store or analytics:** the person enters identifiers and the key in the secure form at `https://app.sprid.studio/settings/app-profiles`. Credentials never go in chat, tool arguments or reports. A saved-key indicator only proves configuration; `get_marketing_review` does a live read.\n\n## Bring images or a finished video\n\nDraft copy in the chat, in the account’s voice. No extra model key needed.\n\nIf the chat exposes the attached files, pass them to `import_assets`: each file has `download_url` and `file_id`, optionally `mime_type` and `file_name`. Public HTTPS URLs and existing `{kind, id}` library references also work. Limits: PNG, JPEG, WebP or finished MP4, up to 32 MiB each. Each position reports on its own; retry the missing ones before building the post. Files are copied to the account and deduplicated by bytes; temporary download URLs are not kept.\n\nA `sandbox:` URL or local path can’t be fetched. For an image the chat generated, use the existing file if the host exposes it (not verified for every host); otherwise download it and use the browser upload. Never ask the agent to recreate an image or transcribe binary data.\n\n**Fallback: browser upload.** Call `create_upload_session` with the account and a new UUID `requestId`. The person opens the link and picks the files. Then read `get_studio_job` with the returned ID; its result keys are zero-based positions. The same session and asset IDs work from any other chat. No image-generation charge.\n\n## Create and review the post\n\nCall `create_post` with a new UUID `requestId`, the account, ordered `{kind, id}` assets, captions and aspect ratio. Reuse the same ID and inputs if a response is lost.\n\n- `presentation: \"finished\"` keeps artwork as-is: no text overlay, no added music. Images fit inside the canvas, which can add margins.\n- `presentation: \"editable\"` allows `text` and `subtitle` on image slides.\n- One finished video becomes one reel. Never mix a video with image slides.\n\nEdit with `update_post` (captions) and `update_slides` (slides). Call `preview_post` and check every slide or the video: captions, order, crop, legibility. It returns a small image of each slide for the agent to look at and an embedded preview for the person; a chat without embedded apps still shows the images. A preview is not approval to publish.\n\nAgent: show the person the preview, and link every post you mention with the `links` the tools return, as a Markdown link on its ref or title: `links.review` when the ask is to approve or schedule, `links.editor` when it is to change something. Never draw the slides in your own widget or artifact: those sandboxes block Sprid's media host and the images show broken.\n\n## Make a reel from photos or text\n\nCheck `get_capabilities` for hosted creation first. `create_reel` takes ordered scenes (`imageId`, `text`, `durationMs`), up to 120 seconds, and makes a silent MP4. It costs 3 Sprid credits per started render minute, or uses the plan allowance: check `spend_status`, tell the person, and get their go-ahead before sending `confirmed: true`. Save the job ID and read `get_studio_job`. Retrying with the same ID never starts a second render; a stopped job reports `needs_attention` instead of charging again.\n\nTo turn an existing post's slides into a video instead, use its own video: `get_video_capabilities`, then `get_post_video` and `edit_post_video` for transitions and motion, and `update_post {outputs}` for which destinations get it. Rendering it is metered the same way: `quote_post_video_render`, the person's go-ahead, then `render_post_video` with `confirmed: true`. Schedule a video destination with the render's `videoRenderId`.\n\nApp captures, simulator recordings and your own build scripts run outside remote MCP. Upload their finished files.\n\n## Approve and confirm delivery\n\nPublishing and scheduling require the person's approval of the preview and intended destinations. The browser review link remains available for picking channels, time and platform options.\n\nTikTok requires an explicit `postMode`; nothing defaults to a direct post or a draft:\n\n- `MEDIA_UPLOAD` sends the media to the creator's TikTok inbox. They finish the post in TikTok; report it as a draft.\n- `DIRECT_POST` requires `privacyLevel`, `disableComment`, `disableDuet`, `disableStitch`, `yourBrandToggle`, `brandedContentToggle` and `confirmed: true` in `options.tiktok`. Fetch fresh choices with `list_connections {includeTikTokCreatorInfo: true}` and show the creator identity, media and caption. The person chooses every setting for this post. Photo posts use `disableDuet: true` and `disableStitch: true`; comments respect the creator's restriction. Branded content cannot use `SELF_ONLY`.\n\nBefore sending `confirmed: true`, get the person's approval of this exact post and their agreement to TikTok's [Music Usage Confirmation](https://www.tiktok.com/legal/page/global/music-usage-confirmation/en), plus the [Branded Content Policy](https://www.tiktok.com/legal/page/global/bc-policy/en) for branded content. That flag is a caller's attestation, not proof of a click in TikTok's prescribed UI. Never invent choices or carry usual preferences into a new post. If choices are missing, open the returned `approvalUrl` for the person to answer in Sprid.\n\nAn approval covers the version the person saw. If you edit a scheduled direct post afterwards, the edit's result carries `tiktokApproval`: the scheduled post will not publish as it is. Show the person the change and the settings in its `rebook` call, ask whether to post this version, and only after they agree call `rebook` with `options.tiktok.confirmed: true` added. `post_queue` returns the same call while the approval is outstanding.\n\nTikTok's published guidelines specify a privacy dropdown and posting controls. Acceptance of this chat-based confirmation flow has not been verified with TikTok. Keep that distinction explicit in review submissions.\n\nAfter approval, read `post_queue`. Keep draft, scheduled, failed and delivered apart, and report delivery only with the platform receipt. Read a failure before retrying. Never repeat a publish call just because a response was lost.\n\nFor results, read `get_documentation` for `marketing-review`. Keep the same app, account and post IDs across clients. `next_actions` gives the next step; an empty `verb` means follow its browser link.\n\n## Limits and troubleshooting\n\n- **Attachment can’t be read:** use the browser upload, not the CLI.\n- **Missing account or service:** set it up in the dashboard. Never paste credentials into chat.\n- **Hosted creation:** check `get_capabilities` before promising it. Store screenshots and store releases are local unless it reports otherwise.\n- **File transfer:** whether a host exposes uploaded or generated files has to be checked per host. A supported schema doesn’t prove it.\n",
|
|
1669
|
+
"revision": "65ac7d19472b2e66"
|
|
1670
1670
|
},
|
|
1671
1671
|
{
|
|
1672
1672
|
"id": "local",
|
|
@@ -1708,13 +1708,21 @@ export const CONTENT_GUIDES = [
|
|
|
1708
1708
|
"markdown": "# Why a post travels\n\n**What this guide does:** Explains what Instagram and TikTok actually reward,\nand turns each mechanic into a rule you can build a post against. Read it before\ndeciding a format, a slide count or a caption length, and when a post that\nlooked good got no reach. Pinterest works on search and has its own guide,\n[Pinterest content and publishing](pinterest.md).\n\nWhether a post is *good* and whether it *travels* are two different questions.\nThis one is about the second. Every rule here exists because of a specific\nmechanic, and if the mechanic changes the rule goes with it, so each one carries\nits reason.\n\n**Verified against published sources 2026-08-04.** Platform mechanics decay.\nTreat anything here as a claim about a moving system, re-check it quarterly, and\nprefer your own numbers the moment you have them.\n\n## Instagram\n\n**The three named ranking signals are watch time, sends per reach, and likes per\nreach.** Sends are the heaviest, reported at roughly three to five times the\nweight of a like. Sends per reach is specifically the signal that reaches people\nwho do not follow you, which is the only reach a new account can grow on.\n\n**Feed, Reels, Stories and Explore rank separately** and weight those signals\ndifferently. Feed leans on how close you already are to the viewer; Explore on\nengagement velocity and interest match. A post that does well with your existing\nfollowers is not automatically a post that travels.\n\n**Why carousels, specifically:**\n\n- Every swipe is engagement, and dwell time accumulates across the slides.\n Carousels are reported at two to three times the reach of a single image for\n the same content.\n- **The platform re-serves a carousel to people who did not swipe, starting from\n the second slide.** This is the most actionable mechanic available: slide two\n gets an independent second chance to be someone's first impression.\n- Carousels out-save single images by a wide margin, and saves compound, because\n saved posts get resurfaced.\n- Completion - how many people reach the last slide - is what pushes a post out\n of your followers and into Explore.\n\n**Hashtags do not drive distribution.** The platform's own position is that they\ncategorise rather than distribute. Discovery comes from the words in your\ncaption: captions, alt text, bios and on-screen text are indexed and served into\nin-app search. Keyword-rich captions have been measured at around 30% more reach\nthan hashtag-heavy ones. Keep three to five hashtags as labels and spend the\neffort on the prose.\n\n## TikTok, photo mode\n\n- Ranking is swipe-through rate, dwell time and reverse swipes, with completion\n rate as the primary signal.\n- Distribution starts with a **small test batch of roughly 200-500 viewers**,\n mostly followers and people who engage with adjacent content. What that batch\n does decides everything afterwards. This is why the first hour matters, and\n why a weak second slide can end the post’s reach.\n- Saves are weighted and photo posts save well. A carousel with fewer views but\n a high save-and-comment share is doing better than a higher-view post that\n bounces on slide one.\n- Interest-based distribution means an outlier is possible from your first post.\n TikTok is spikier; Instagram grinds.\n\n## Pinterest\n\nThe rules below are for Instagram and TikTok and do not apply to a Pin.\nPinterest is visual search: a Pin is found through search, home feeds and\nrelated Pins for months, mostly regardless of followers, so there is no\nfirst-hour test batch and no second slide. Relevance comes from the image, the\ntitle and description, the board and the page the link opens. Judge Pins at\nequal ages (30, 60 and 90 days) by outbound clicks and what they lead to on\nyour site.\n\n## What follows for how you build a post\n\n| Rule | Because |\n|---|---|\n| **Slide 2 is a second hook.** It delivers on slide 1 *and* opens a new thread, and it has to work cold | the platform re-serves from slide 2; TikTok's test batch dies there |\n| **Seven slides for a narrative format** (hook, five body, closer) | seven to ten is the reported dwell-time sweet spot; under five reads as a short post, over ten causes mid-carousel fatigue |\n| **No slide may be skippable.** If a body slide can be removed without breaking the post, you wrote a list, and people can stop anywhere in a list | completion is the ranking signal, and a list lets people stop anywhere |\n| **The peak lands in the last third** | a middle peak makes the tail a letdown, and the tail is where completion is won |\n| **Design for sends.** At least one slide should make someone think of a specific person | sends per reach is the non-follower signal, worth several likes |\n| **The send prompt lives in the caption**, naming one kind of person, never \"share if you relate\" | it belongs where sends are earned, and it keeps the last slide screenshottable |\n| **At least two slides hand over something usable** | recognition earns likes; recognition plus something doable earns saves, and saves compound |\n| **Captions carry the audience's own search phrases, in prose** | captions are indexed; hashtags are not distribution |\n| **Caption length 400-600 characters on Instagram, 150-300 on TikTok**, first line an independent hook under 125 characters | that is where the \"more\" cut falls; past roughly 300 characters TikTok needs a tap and reach drops |\n| **Three to five hashtags, never the generic feed tag** | labels, not reach |\n| **One canvas at 4:5, content clear of the top and bottom edges** | survives the 3:4 grid crop, letterboxes acceptably on TikTok |\n\n## Cadence, and the first hour\n\n**Three to five posts a week, sustained.** Three a week for twelve weeks beats\nseven a week for three. The failure mode is not low quality, it is stopping - and\nthe documented version of it is 34 drafts and 3 published posts.\n\n**The first hour is the test batch.** Being there to answer early comments is the\ncheapest intervention available on either platform; a comment answered in the\nfirst hour is worth more than the same reply a day later.\n\n**Post at a fixed time** your audience is awake for, set once on the account's\nposting schedule rather than decided per post.\n\n**Expect silence for two months.** A new account with no face takes three to six\nmonths to reach a thousand followers on Instagram. Distribution is a power law:\na few posts carry most of the reach. Judging before 90 days is judging noise.\n\n## When something works, fan it out\n\nWhen a post breaks out, the work starts: more like it, and the best one promoted.\n\n1. Make five to ten variants of the winner with the structure fixed and **exactly\n one variable changed** - the hook phrasing, the register, the opening image.\n2. One variable per variant, or the result teaches nothing.\n3. Log which variant won *and* which source line its hook came from. That tells\n you which well to keep digging.\n4. A losing variant tells you something. Stop it and write down what.\n\n## What is worth not believing\n\nEverything above is published guidance and platform statements, not our\nmeasurements. Before you treat any of it as settled for **your** audience, these\nare the clean one-variable tests: caption length judged on saves and sends per\nreach; a quiet text card against a photo behind text; a native 9:16 crop against\na letterboxed 4:5; whether a screenshot of your app costs reach or buys installs.\n\nLog the real numbers per post at seven days - views, completion, saves, sends,\ncomments, profile taps. The moment you have your own numbers they outrank every\nsource below.\n\n## Sources\n\n- [Instagram algorithm ranking signals (Buffer)](https://buffer.com/resources/instagram-algorithms/) - watch time, sends per reach, likes per reach, per-surface ranking\n- [The ranking signals that matter (Clixie)](https://www.clixie.ai/blog/instagram-algorithm) - sends weighted three to five times a like\n- [How carousels beat Reels for engagement (Storrito)](https://storrito.com/resources/how-instagram-carousels-beat-reels-for-engagement-in-2026-and-when-to-use-each/) - re-serving from slide 2, reach multiple\n- [Carousel best practices (Adpicto)](https://www.adpicto.com/en/blog/instagram-carousel-best-practices-2026) - slide count, dwell time, saves\n- [Carousel algorithm (TryMyPost)](https://www.trymypost.com/blog/instagram-carousel-algorithm-strategy-2026) - dwell time and completion\n- [Do hashtags still work (Kontentino)](https://www.kontentino.com/q-and-a/instagram-hashtags-reach/) - hashtags do not drive reach\n- [Keywords versus hashtags (Dive Media)](https://www.divemedia.com.au/marketing-tips-and-insights/social-seo-keywords-vs-hashtags) - caption indexing and the reach lift\n- [TikTok photo mode algorithm (ReelBase)](https://reelbase.io/blog/tiktok-photo-mode-algorithm-explained) - photo mode reach against video\n- [TikTok carousel algorithm (PostWaffle)](https://www.postwaffle.com/blog/tiktok-carousel-algorithm) - swipe-through, reverse swipes, test batch size, saves\n",
|
|
1709
1709
|
"revision": "1fdc948323095b06"
|
|
1710
1710
|
},
|
|
1711
|
+
{
|
|
1712
|
+
"id": "meta-conversions",
|
|
1713
|
+
"title": "Run your first Meta conversion campaign.",
|
|
1714
|
+
"summary": "Takes you from Meta account setup to a conversion campaign prepared in Sprid, with a real event checked before you approve spending.",
|
|
1715
|
+
"url": "https://sprid.studio/docs/meta-conversions",
|
|
1716
|
+
"markdown": "# Run your first Meta conversion campaign.\n\n**What this guide does:** Takes you from Meta account setup to a conversion campaign prepared in Sprid, with a real event checked before you approve spending.\n\nA conversion campaign asks Meta to find people likely to complete an action in your app. Choose the action you want, prove that Meta receives it, then build the campaign. Your agent prepares the ads. You review the campaign and press Launch in Sprid.\n\n## You need.\n\n- Admin access to the Meta business portfolio and ad account that will pay for this app’s ads.\n- A Facebook Page for the app, linked to its professional Instagram account if you want Instagram delivery.\n- Access to your app’s server and domain DNS. A developer needs to send your conversion events to Meta.\n- A Sprid account connected to Meta Ads, and a person signed in to Sprid to approve the reviewed budget.\n\n## Set up Meta once.\n\n1. **Create or choose the business portfolio.** Keep the app’s Page, ad account and dataset under the business that owns them. Your personal Facebook login administers those assets.\n2. **Create the Page and link Instagram.** The Page supplies the identity for the ad, including ads that run only on Instagram. Check the linked handle before connecting Sprid.\n3. **Choose or create the ad account and add billing.** Choose its currency and time zone carefully. Changing them creates a new ad account and closes the old one, stopping its ads. Sprid’s budget amounts use the connected ad account’s currency.\n4. **Create the dataset in Events Manager.** This is where Meta receives conversion events. Keep its ID. A server-only Conversions API integration can use the dataset without installing browser pixel code.\n5. **Verify the app’s domain.** In Meta’s business settings, follow domain verification and add the supplied DNS TXT record with your DNS provider. Verify the domain where your conversions happen.\n6. **Create the Conversions API token.** Use the dataset’s direct integration setup in Events Manager. Save the token in your server’s secret settings. This token sends your app’s events; Sprid’s Meta Ads connection manages campaigns separately.\n7. **Review account-level advertising settings.** Check any optional AI tests that change the destination or its presentation. Your agent’s creative settings cannot prove what an account-level test will do. If you use Meta’s audience-segment reports, define the engaged audience and existing customers there before interpreting those reports.\n8. **Connect Meta Ads to Sprid.** Follow [Connect Meta Ads](https://sprid.studio/docs/connect/meta-ads), selecting this app’s Page, ad account and dataset. Set the daily, campaign and monthly spending caps in Sprid’s account settings. If several apps share the ad account, a workspace owner or admin also sets **Shared Meta limits** there. Each app keeps its own Page and dataset; the shared limits cover campaigns managed through Sprid.\n\n## Prove the conversion signal.\n\n1. In Events Manager, select the dataset and open **Test events**. Add its test code to your server’s Conversions API request as `test_event_code`.\n2. Complete the chosen action through the app. Check that Events Manager receives the exact event name and reports a server connection. A successful HTTP request alone does not prove the expected event arrived.\n3. Inspect the event details. Website events need `event_source_url` and the visitor’s `client_user_agent`. Send a stable `external_id` for matching. When a real Meta click supplies `fbclid`, preserve it through redirects and send the correctly formatted `fbc` value. Keep the click ID’s case unchanged.\n4. Check `Purchase` with the actual paid amount and currency if the app sells something. Store the visitor’s user agent and click ID when they arrive, so a later payment webhook can use the original values.\n5. Remove `test_event_code` for production. Complete another real action and check its arrival, then ask your agent to run `dataset_health` for the event you will optimize on.\n\nEmail and phone identifiers need Meta’s normalization and hashing. Hashing `external_id` is recommended; keep its representation consistent across integrations. `fbc` and `client_user_agent` must remain unhashed. See [customer information parameters](https://developers.facebook.com/documentation/ads-commerce/conversions-api/parameters/customer-information-parameters) when implementing the server call.\n\nTest codes identify test payloads. Meta says those events still flow into Events Manager and can be used for targeting and measurement. Test only with actions you actually perform, then remove the code.\n\n`dataset_health` checks recent event counts and, when Meta provides it, event match quality. Its count check covers seven days and Meta’s top 100 events per hour. An event absent from that response is unobserved. A match-quality score does not prove that a recent conversion happened.\n\n## Choose an event that predicts payment.\n\nUse `Purchase` when purchases happen often enough to give the campaign a useful signal. If purchases are sparse, choose a completed action in the same visit that customers take before paying. Check the connection to payment in your own analytics.\n\nMeta says ad sets usually leave learning after about 50 results in the week following the last significant edit. This is guidance about stable delivery. Results below that volume can still tell you about a broken checkout or whether anyone paid.\n\nStandard events use their exact names, such as `Purchase`, `Lead` or `CompleteRegistration`. For your own event, such as `RecipePlanCompleted`, ask your agent to:\n\n1. Run `dataset_health` without a conversion selection and find the exact name in `datasetHealth.events`. Check that the returned `datasetId` is the connected dataset you intend to use. The readiness result may still ask you to select a conversion.\n2. Run `list_custom_conversions` to check for an existing matching rule.\n3. If needed, call `create_custom_conversion` with a name and the exact `eventName`. Keep the returned ID.\n4. Complete the action again after creating the rule. The custom conversion itself must have a recent fire before launch; an earlier underlying event cannot prove a new rule worked.\n\nA custom conversion is a named rule on events in your dataset. Sprid creates a case-sensitive event-name rule. The ad set selects that rule by `customConversionId`.\n\n## Build the campaign through Sprid.\n\nGive your agent the intended countries, total budget, run length, destination and hypothesis. State the regulated category before the campaign is created. Housing, employment, financial products and services have targeting restrictions; declare `NONE` only when no category applies. [Meta’s category guide](https://developers.facebook.com/docs/marketing-api/audiences/special-ad-category/) explains the scope.\n\nAsk the agent to follow this order:\n\n1. **Check readiness:** `ads_overview`, then `dataset_health` with the chosen `conversionEvent`. Fix missing connections or an unobserved event before creating ads.\n2. **Create the paused campaign:** `create_ad_campaign` with an objective such as `OUTCOME_SALES` and explicit `specialAdCategories`. Political campaigns also need explicit `countries`. For housing, credit and employment, Sprid derives the campaign countries from the ad sets.\n3. **Create the paused ad set:** `create_ad_set` with `OFFSITE_CONVERSIONS`, the chosen event, countries and reviewed budget. Use explicit Facebook and Instagram Feed, Stories and Reels placements for paired creatives. Set `targetCostPerEventCents` as the cost you will judge results against. This is a reporting target, not a bid. Use `startAt` if you want a later start.\n4. **Prepare the creative:** `render_ad_creative` builds from a named template, or `create_ad_creative` accepts your own material. Ask for feed and vertical assets. An external pair must identify whether its assets are images or videos. Keep `destinationUrl` free of hand-written `utm_*` parameters; Sprid adds tracking.\n5. **Attach and review:** use `create_ads` to attach the creatives, review each one with `review_ad_copy`, then run `ads_preflight`. Check previews for Feed, Stories and Reels. A passing comparison confirms the stored fields checked against Sprid’s intent; it does not guarantee Meta will approve delivery.\n6. **Approve in Sprid:** `launch_ads` returns the reviewed commitment and an `approvalUrl`. Open that link, check the amount and end date, then press Launch. The agent cannot start spending or raise the budget.\n\nThe following is a fictional ad-set input for Pantry Note on a USD ad account. The IDs are examples. Choose your own budget and target cost before preparing a campaign.\n\n```json\n{\n \"account\": \"pantrynote\",\n \"campaignId\": \"00000000-0000-4000-8000-000000000001\",\n \"name\": \"Completed recipe plan\",\n \"optimizationGoal\": \"OFFSITE_CONVERSIONS\",\n \"conversionEvent\": { \"customConversionId\": \"123456789\" },\n \"dailyBudgetCents\": 1000,\n \"durationDays\": 7,\n \"countries\": [\"US\"],\n \"targeting\": {\n \"publisher_platforms\": [\"facebook\", \"instagram\"],\n \"facebook_positions\": [\"feed\", \"story\", \"facebook_reels\"],\n \"instagram_positions\": [\"stream\", \"story\", \"reels\"]\n },\n \"targetCostPerEventCents\": 500,\n \"hypothesis\": \"Showing the completed meal plan brings customers who purchase.\"\n}\n```\n\nFor a standard event, use `\"conversionEvent\": {\"standard\": \"Purchase\"}`.\n\nSprid requests opt-outs for the documented creative enhancements it supports and checks Meta’s stored settings before launch. It supplies feed and vertical assets when paired material is available. Conversion ad sets store explicit attribution settings: seven-day click, one-day view and one-day engaged video view. A mismatch found by preflight blocks launch.\n\n## Read where people stop.\n\nUse `ad_status` to check delivery and rejection messages. Ask for `ad_council` to compare cost per optimized event with your target. Then compare Meta’s clicks with your app’s actual outcomes.\n\nThe stage-by-stage diagnosis below is a manual check using Meta reports and your own analytics. Sprid’s automatic combined funnel diagnosis is planned.\n\n| Stage | Compare | Investigate when that stage loses people |\n|---|---|---|\n| Ad | Link clicks per impression | The opening, image or promise |\n| Page loads | Landing-page views per link click | Load errors, slow pages or redirects |\n| App starts | Started actions per landing-page view | Message match and the first action |\n| App completes | Completed actions per started action | Product failures or confusing steps |\n| Customer pays | Paid customers per completed action | The offer, price presentation or checkout |\n\nCompare a consistent cohort and period. Repeat actions by one person are different from independent potential buyers. Keep campaign totals separate from their ad-set totals, since they overlap.\n\nWith zero purchases, the table gives approximate one-sided 95% upper bounds on the purchase rate. It assumes independent comparable people, complete measurement and enough follow-up for them to purchase. Use it to decide what to investigate; a sample alone cannot prove an offer will fail.\n\n| Completed actions from different people, with zero purchases | Approximate upper bound |\n|---|---|\n| 30 | 10% |\n| 60 | 5% |\n| 100 | 3% |\n\nCompare that bound with the purchase rate your margins require. Confirm checkout and purchase tracking work before blaming the offer. [The statistical rule](https://jhanley.biostat.mcgill.ca/c607/ch08/zero_numerator.pdf) explains the approximation.\n\nChanges to targeting, creative or the optimization event can restart learning. Budget changes depend on their size. Record each campaign change and its reason. Fix product and checkout bugs when you find them; changing page content alone is different from editing the ad’s destination or creative.\n\n## If it fails.\n\n- **No recent event observed:** check the dataset ID and server response, perform the action, then recheck Events Manager. Remove the test code before the production check.\n- **Custom conversion has no recent fire:** confirm its dataset and exact event-name rule. Perform the action after the rule exists. Do not substitute an unrelated standard event to pass the check.\n- **Match quality unavailable:** Meta may need dataset permission or an opt-in. Read the score in Events Manager while you resolve access. Missing quality does not turn an observed event into zero.\n- **Preflight names a mismatch:** correct the named setting, or recreate the paused ad set or creative through Sprid when it cannot be edited. Run preflight again. Avoid changing tracked fields independently in Ads Manager.\n- **Budget exceeds a cap:** review the daily and total commitment in Sprid’s account settings. A person must approve the spending limit or budget change in the app.\n- **No purchases yet:** verify measurement, then read the completed-action count and follow-up period. A small cohort is inconclusive.\n\n## Sources.\n\nMeta references checked 14 October 2026. Account-specific acceptance still needs a paused create and readback on your connected account.\n\n- [Meta Ads connection](https://sprid.studio/docs/connect/meta-ads) and [ad-account currency changes](https://www.facebook.com/business/help/291404291014138).\n- [Conversions API: sending and testing events](https://developers.facebook.com/documentation/ads-commerce/conversions-api/using-the-api), [server event parameters](https://developers.facebook.com/documentation/ads-commerce/conversions-api/parameters/server-event), and [click ID handling](https://developers.facebook.com/documentation/ads-commerce/conversions-api/parameters/fbp-and-fbc).\n- [Custom conversions](https://developers.facebook.com/docs/marketing-api/reference/custom-conversion/) and [dataset quality](https://developers.facebook.com/documentation/ads-commerce/conversions-api/dataset-quality-api).\n- [Learning phase](https://www.facebook.com/business/help/112167992830700) and [significant edits](https://www.facebook.com/business/help/316478108955072).\n",
|
|
1717
|
+
"revision": "6b190d8339bfa320"
|
|
1718
|
+
},
|
|
1711
1719
|
{
|
|
1712
1720
|
"id": "ads",
|
|
1713
1721
|
"title": "Ads: pay to show more people what already worked",
|
|
1714
1722
|
"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.",
|
|
1715
1723
|
"url": "https://sprid.studio/docs/ads",
|
|
1716
|
-
"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. Spending starts only when you press Launch or Confirm in the Sprid app,\non a screen that shows what will run, what it costs a day and for how long. An\nagent can prepare a campaign and send you that link. It can't start one or\nraise a budget itself.\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**
|
|
1717
|
-
"revision": "
|
|
1724
|
+
"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. Spending starts only when you press Launch or Confirm in the Sprid app,\non a screen that shows what will run, what it costs a day and for how long. An\nagent can prepare a campaign and send you that link. It can't start one or\nraise a budget itself.\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**Check how much evidence you have.** Meta says ad sets usually leave learning\nafter about 50 results in the week following the last significant edit. That\nis delivery guidance. A smaller sample can still expose a broken checkout.\nSprid’s three-day early-observation flag describes its own review policy;\nit does not report Meta’s learning status. Read the sample and follow-up period\nbefore deciding whether an offer 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\nFor a campaign that optimizes for a signup or purchase, follow\n[Run your first Meta conversion campaign](https://sprid.studio/docs/meta-conversions).\nIt covers server events, custom conversions and the fresh checks before launch.\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- You, signed in to the Sprid app, to press Launch. No agent or token can.\n",
|
|
1725
|
+
"revision": "39522800c08ab728"
|
|
1718
1726
|
},
|
|
1719
1727
|
{
|
|
1720
1728
|
"id": "reel-first-seconds",
|