openclaw-adspirer 2026.3.13 → 2026.3.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
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.3.16 (2026-03-16)
4
+
5
+ ### Added
6
+ - **Placement-specific image creatives** for Meta campaigns — use different images for Feed (1080x1080), Stories/Reels (1080x1920), and Right Column (1200x628) via `asset_feed_spec`
7
+ - Auto-detection of Page-Backed Instagram Account (PBIA) for `asset_feed_spec` creatives
8
+ - `story_image_url` and `right_column_image_url` parameters for `create_meta_image_campaign` and `add_meta_ad`
9
+ - **City-level targeting** for Meta campaigns — target specific cities with optional radius
10
+ - **Emoji/rich text support** in Meta `primary_text` — emojis, line breaks, bullet points for higher engagement
11
+ - Graceful fallback to standard `object_story_spec` when placement image uploads fail
12
+
13
+ ### Fixed
14
+ - Meta `asset_feed_spec` requires explicit `instagram_user_id` (unlike `object_story_spec` which auto-assigns)
15
+ - Meta `asset_customization_rules` requires at least 2 rules — single-image fallback prevents API errors
16
+
17
+ ## 2026.3.15 (2026-03-15)
18
+
19
+ ### Added
20
+ - **Input format requirements** section in embedded skill prompt — guides AI clients on IDs-as-strings, text length limits, enum casing, budget types, and keywords format
21
+ - Server-side input resilience: auto-coerces int IDs to strings, normalizes enum casing, strips whitespace, ignores unknown fields, parses JSON string arrays
22
+
23
+ ### Fixed
24
+ - Reduced ~160 preventable validation errors (22% of all tool call failures) through server-side coercion and client-side guidance
25
+
3
26
  ## 2026.3.7 (2026-03-07)
4
27
 
5
28
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-adspirer",
3
- "version": "2026.3.13",
3
+ "version": "2026.3.16",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin for Adspirer — manage Google, Meta, TikTok & LinkedIn ads via natural language",
6
6
  "keywords": [
@@ -16,7 +16,7 @@ import { readFileSync, writeFileSync, rmSync, existsSync } from "node:fs";
16
16
  import { join } from "node:path";
17
17
 
18
18
  const PLUGIN_ID = "openclaw-adspirer";
19
- const PLUGIN_VERSION = "2026.3.13";
19
+ const PLUGIN_VERSION = "2026.3.16";
20
20
 
21
21
  function getConfigPath(): string {
22
22
  return join(process.env.HOME || process.env.USERPROFILE || ".", ".openclaw", "openclaw.json");
package/src/errors.ts CHANGED
@@ -7,7 +7,7 @@ export function mapHTTPError(status: number, body?: any): string {
7
7
  case 401:
8
8
  return "Session expired. Run 'openclaw adspirer login' to reconnect.";
9
9
  case 402:
10
- return "This feature requires Adspirer Plus/Pro. Upgrade at https://adspirer.ai/settings?tab=billing";
10
+ return "This feature requires Adspirer Plus/Pro. Upgrade at https://adspirer.ai/";
11
11
  case 403:
12
12
  return "Access denied. Check account permissions or subscription tier.";
13
13
  case 404:
@@ -203,6 +203,65 @@ These tools operate on REAL ad accounts that spend REAL money. Follow strictly:
203
203
 
204
204
  ---
205
205
 
206
+ ## Critical: Input Format Requirements
207
+
208
+ Follow these rules EXACTLY when calling Adspirer tools to avoid validation errors:
209
+
210
+ ### IDs Must Be Strings
211
+ All IDs (campaign_id, ad_account_id, video_id, image_hash, ad_group_id, keyword_id, organization_id, creative_id) MUST be passed as quoted strings, never as bare integers.
212
+
213
+ - ✅ \`"existing_video_id": "1333064875515942"\`
214
+ - ❌ \`"existing_video_id": 1333064875515942\`
215
+
216
+ ### Never Modify IDs
217
+ Copy IDs exactly as returned by list/discover tools. Do not round, truncate, or change any digits. If \`list_campaigns\` returns \`campaign_id: "120240129373510507"\`, use that exact value.
218
+
219
+ ### Always Call List/Discover Before Create/Update
220
+ Many tools require IDs from prior tool calls:
221
+ - \`list_campaigns\` → get \`campaign_id\` before update/pause/structure
222
+ - \`get_campaign_structure\` → get \`ad_group_id\` before keyword operations
223
+ - \`discover_existing_assets\` → get \`image_hash\`, \`video_id\` before campaign creation
224
+ - \`get_linkedin_organizations\` → get \`organization_id\` and \`account_id\`
225
+
226
+ ### Text Length Limits
227
+ Respect character limits — the server will reject text that's too long:
228
+ - Google Ads headline: max 30 characters
229
+ - Google Ads description: max 90 characters
230
+ - Google Ads sitelink text: max 25 characters
231
+ - Google Ads callout: max 25 characters
232
+ - Meta primary_text: max 125 characters (supports emojis, line breaks, bullet points)
233
+ - Meta headline: max 40 characters
234
+
235
+ ### Meta Ad Copy Formatting
236
+ Meta primary_text supports rich formatting for higher engagement:
237
+ - Use emojis strategically: \`\`🔥 ✅ 🎯 💰 ⚡ 🚀 👉 ⭐\`\`
238
+ - Use line breaks (\\n) and bullet points (•, ✅, ▸) for readability
239
+ - Example: \`\`"🔥 Limited Time Offer!\\n\\n✅ Free Shipping\\n✅ 30-Day Returns\\n\\n👉 Shop now!"\`\`
240
+ - Bold/italic/HTML are NOT supported — plain text with emojis only
241
+
242
+ ### Enum Values Are Case-Insensitive
243
+ The server auto-normalizes casing, but these are the expected values:
244
+ - **status:** ENABLED, PAUSED, ACTIVE, ARCHIVED
245
+ - **objective:** OUTCOME_TRAFFIC, OUTCOME_SALES, OUTCOME_LEADS, etc.
246
+ - **match_type:** EXACT, PHRASE, BROAD
247
+ - **call_to_action:** LEARN_MORE, SHOP_NOW, SIGN_UP, etc.
248
+ - **date_range:** last_7_days, last_30_days, last_90_days, etc.
249
+ - **campaign_type:** search, pmax, image, video, carousel, etc.
250
+
251
+ ### Budgets Are Numbers
252
+ Pass budget fields (\`budget_daily\`, \`budget_amount\`, \`target_cpa\`) as numbers, not strings:
253
+ - ✅ \`"budget_daily": 50\`
254
+ - ❌ \`"budget_daily": "50"\`
255
+
256
+ Budget is in the account's local currency (not cents). Meta minimum varies by currency.
257
+
258
+ ### Keywords Format
259
+ For \`add_negative_keywords\`, each keyword must be an object:
260
+ - ✅ \`"keywords": [{"text": "free", "match_type": "BROAD"}]\`
261
+ - ❌ \`"keywords": ["free", "cheap"]\`
262
+
263
+ ---
264
+
206
265
  ## Platform Quick Reference
207
266
 
208
267
  ### When to Use Each Platform
@@ -277,7 +336,7 @@ Adspirer is billed by tool calls \u2014 each API action (reading performance, cr
277
336
 
278
337
  All plans include access to all ad platforms (Google Ads, Meta Ads, LinkedIn Ads, TikTok Ads). Tool call quotas reset monthly.
279
338
 
280
- Sign up and connect ad accounts at https://adspirer.ai/settings?tab=billing
339
+ Sign up and connect ad accounts at https://adspirer.ai/
281
340
 
282
341
  ---
283
342
 
@@ -314,5 +373,5 @@ Sign up and connect ad accounts at https://adspirer.ai/settings?tab=billing
314
373
  | Session expired | Token auto-refreshes; if persistent, run login again |
315
374
  | No platform data | Connect ad platforms at https://adspirer.ai/connections |
316
375
  | Wrong account active | Use \`switch_primary_account\` to change |
317
- | Tool call quota exceeded | Upgrade plan at https://adspirer.ai/settings?tab=billing (Free: 15/mo, Plus: 150/mo, Pro: 600/mo, Max: 3,000/mo) |
376
+ | Tool call quota exceeded | Upgrade plan at https://adspirer.ai/ (Free: 15/mo, Plus: 150/mo, Pro: 600/mo, Max: 3,000/mo) |
318
377
  `;