agentleFS
gomarble-aigomarble-ai/marketing-agent/skills/meta-tool-fundamentals/SKILL.md

meta-tool-fundamentals

Skill15 starsChanged 38 days agoMITView on GitHub

Foundation tool reference for any Meta (Facebook/Instagram) Ads task — Marketing API quirks, common entity relationships, currency in cents. Used internally when working with Meta tools.

The file

Show its rules and text

We split this skill into the rules it gives an agent

19 rules. About 0 are common, 4 are distinctive, and 15 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 15

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Default filtering: Always apply filtering=[{"field":"impressions","operator":"GREATER_THAN","value":0}] unless user wants non-delivered …

    line 28
  2. Very specific:

    Active entity filtering (CRITICAL): When analyzing current performance, ALWAYS add an effective_status filter to exclude paused/deleted …

    line 30
  3. Very specific:

    Only omit the effective_status filter when the user explicitly asks for historical or paused entity data.

    line 37
  4. Very specific:

    Default sorting: Use sort='spend_descending' unless user specifies otherwise.

    line 39
  5. Very specific:

    Breakdowns: Only include when specifically requested.

    line 41
  6. Very specific:

    Creative fatigue analysis: Use time_increment='1' for daily trend data.

    line 43
  7. Very specific:

    Rule: Use ONLY ONE. Check omni_purchase first.

    line 51
  8. Distinctive:

    Before using Meta insights data for totals, rankings, CPA/ROAS, budget allocation, campaign comparisons, or Python/advanced analysis:

    line 56
  9. Very specific:

    Call facebook_fetch_pagination_url with the exact paging.next URL.

    line 57
  10. Distinctive:

    Only then combine pages and analyze.

    line 59
  11. Distinctive:

    Never present totals or conclusions from a partial Meta insights page.

    line 61
  12. Very specific:

    ALL Meta propose tools — facebook_propose_create_campaign_structure AND every facebook_propose_update_* tool — take budgets/bids in ACCOUNT …

    line 64
  13. Very specific:

    Only Meta's RAW response fields — insights and account_structure budget fields — are in cents ($50 = 5000): divide those by 100 when …

    line 66
  14. Very specific:

    Always call facebook_get_details_of_ad_account first.

    line 69
  15. Distinctive:

    Use this to find entity IDs and understand what's running before deeper analysis

    line 72
  16. Very specific:

    If facebook_get_adaccount_insights fails with "reduce the amount of data", use facebook_get_async_adaccount_insights instead.

    line 75
  17. Very specific:

    Use CONTAIN/NOT_CONTAIN for text, GREATER_THAN/LESS_THAN for numbers, IN/NOT_IN for multiple values

    line 82
  18. Very specific:

    Read promoted_object.custom_event_type from the ad set (facebook_get_details_of_ad_account returns it for top spenders.

    line 146
  19. Very specific:

    If promoted_object is missing → ASK the user.

    line 155

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Meta Ads - Tool Fundamentals

How to use Meta Ads tools effectively, plus the canonical metric definitions used across all Meta skills. Auto-loaded with every Meta skill request.

Insights Query Optimization

When using facebook_get_adaccount_insights:

Level selection — use the highest level that answers the question:

  • account — total spend, overall ROAS, account-level metrics
  • campaign — compare campaign performance
  • adset — analyze targeting/audience performance
  • ad — individual ad performance, creative analysis

Field selection — request only what's needed:

  • Basic: spend, impressions, clicks, ctr, cpm, cpc
  • With conversions: add conversions, conversion_values, purchase_roas
  • With names: add campaign_name/adset_name/ad_name matching the level
  • For video: add video_play_actions, video_thruplay_watched_actions

Default filtering: Always apply filtering=[{"field":"impressions","operator":"GREATER_THAN","value":0}] unless user wants non-delivered entities.

Active entity filtering (CRITICAL): When analyzing current performance, ALWAYS add an effective_status filter to exclude paused/deleted entities. The insights API returns data for ANY entity that had spend in the date range, even if it is now inactive.

  • Ad sets: {"field":"adset.effective_status","operator":"IN","value":["ACTIVE"]}
  • Ads: {"field":"ad.effective_status","operator":"IN","value":["ACTIVE"]}
  • Campaigns: {"field":"campaign.effective_status","operator":"IN","value":["ACTIVE"]}

Combine with impressions filter: filtering=[{"field":"impressions","operator":"GREATER_THAN","value":0},{"field":"adset.effective_status","operator":"IN","value":["ACTIVE"]}]

Only omit the effective_status filter when the user explicitly asks for historical or paused entity data.

Default sorting: Use sort='spend_descending' unless user specifies otherwise.

Breakdowns: Only include when specifically requested. Each breakdown multiplies result rows exponentially. Available: age, gender, country, region, publisher_platform, platform_position, device_platform, user_segment_key.

Creative fatigue analysis: Use time_increment='1' for daily trend data.

Date range discipline (CRITICAL): For fixed historical comparisons (named weeks, calendar months, W1/W2/W3, or exact date ranges), use explicit time_range for each period. Do NOT use date_preset unless the user explicitly asks for a relative period such as last_7d, last_14d, this_month, or yesterday.

Purchase De-Duplication (CRITICAL)

Facebook returns overlapping purchase action_types: omni_purchase, purchase, offsite_conversion.fb_pixel_purchase, onsite_web_purchase, web_in_store_purchase, app_custom_event.fb_mobile_purchase.

Rule: Use ONLY ONE. Check omni_purchase first; if absent, fall back to purchase. NEVER sum multiple types — this double-counts revenue and inflates ROAS.

Pagination (CRITICAL)

Meta insights can paginate at ANY level (account, campaign, adset, or ad), especially with breakdowns, time_increment, or broad date ranges. If any Meta insights response contains paging.next or _gomarble_meta_insights_data_quality.paging_next_present=true, the response is incomplete.

Before using Meta insights data for totals, rankings, CPA/ROAS, budget allocation, campaign comparisons, or Python/advanced analysis:

  1. Call facebook_fetch_pagination_url with the exact paging.next URL.
  2. Continue fetching until the latest response has no paging.next and the data-quality block says response_complete=true.
  3. Only then combine pages and analyze.

Never present totals or conclusions from a partial Meta insights page. If pagination cannot be completed, state that the Meta data is incomplete and avoid numeric conclusions from it.

Currency

ALL Meta propose tools — facebook_propose_create_campaign_structure AND every facebook_propose_update_* tool — take budgets/bids in ACCOUNT CURRENCY, human-readable (50 means $50, 300 means ₹300). NEVER convert to cents for a propose tool; the server converts. Values from facebook_get_campaign_details/adset details are already in account currency too.

Only Meta's RAW response fields — insights and account_structure budget fields — are in cents ($50 = 5000): divide those by 100 when displaying. Confirm account currency from facebook_get_details_of_ad_account before presenting monetary values — never assume USD.

Account Context

Always call facebook_get_details_of_ad_account first. It returns:

  • Account currency (for correct monetary display)
  • account_structure with top 10 spending ads, their campaigns and ad sets
  • Use this to find entity IDs and understand what's running before deeper analysis

Async Insights

If facebook_get_adaccount_insights fails with "reduce the amount of data", use facebook_get_async_adaccount_insights instead. Same parameters, handles large datasets asynchronously.

Filtering Guide

  • Status (most important): {"field":"adset.effective_status","operator":"IN","value":["ACTIVE"]}
  • Name matching: {"field":"campaign.name","operator":"CONTAIN","value":"brand"}
  • Performance threshold: {"field":"spend","operator":"GREATER_THAN","value":100}
  • Multiple filters combine as AND conditions
  • Use CONTAIN/NOT_CONTAIN for text, GREATER_THAN/LESS_THAN for numbers, IN/NOT_IN for multiple values

Standard filter combo for current performance analysis:

[
  {"field": "impressions", "operator": "GREATER_THAN", "value": 0},
  {"field": "adset.effective_status", "operator": "IN", "value": ["ACTIVE"]}
]

Metric Glossary

Canonical definitions used across all Meta skills. Workflow skills (meta-creative-analysis, meta-performance-analysis, meta-depth-of-analysis) reference these — they do NOT redefine them.

Direct Metrics (from API response)

MetricAPI FieldHow to Extract
SpendspendDirect
CPMcpmDirect
CTRctrDirect
ImpressionsimpressionsDirect
ClicksclicksDirect
ReachreachDirect
FrequencyfrequencyDirect
Video Playsvideo_play_actions[0].valueInitial impressions of the video
3-Second Viewsactions array, action_type=video_viewHook engagement — NOT a separate field
ThruPlaysvideo_thruplay_watched_actions[0].value15s+ watch or completion
Purchasesactions array, action_type=omni_purchase (fallback purchase)Use ONE only — see Purchase De-Duplication
Leadsactions array, action_type=lead
Revenueaction_values array, action_type=omni_purchase
Purchase ROASpurchase_roasDirect

Additive vs Non-Additive Metrics (CRITICAL)

Additive across complete rows at the same date/entity grain: spend, impressions, clicks, action counts, and action_values after purchase de-duplication.

Non-additive: reach, frequency, ctr, cpm, cpc, cpp, purchase_roas, cost_per_*, CPA/CPR/CPL, and other rate/cost fields. Do NOT sum or average row-level reach or frequency and call it account/campaign/week/month reach or frequency.

For weekly/monthly/account reach or frequency, query facebook_get_adaccount_insights at the exact output level (for example level="account" for account totals) with explicit time_range and no unnecessary breakdown/time_increment. Reach/frequency cannot be recomputed from lower-grain rows.

For rate fields, prefer the API value at the intended grain; otherwise recompute valid rates from additive numerator/denominator fields only after all pages are fetched.

Calculated Metrics

MetricFormulaNotes
Hook Rate(3-sec views / video plays) * 100Uses actions[video_view], NOT video_p25_watched_actions
Hold Rate(thruplays / 3-sec views) * 100
Cost Per Purchasespend / actions[purchase].value
Cost Per Lead (CPL)spend / actions[lead].value
Cost Per Result (CPR)spend / actions[<custom_event>].valueUse the SPECIFIC custom_event_str — never conversions totals
Conversion Rate (CVR)actions[<event>].value / clicks * 100
Budget Utilizationspend / (daily_budget * days_in_period)Daily budget is in cents
Campaign Spend Shareentity_spend / parent_total_spendFor ad-set comparison; require ≥ 25% before comparing
Pareto SetSort ads by spend desc; cumulative spend ≤ 90%These ads drive the majority of activity

Video Funnel

Video Plays → Hook Rate → 3-Second Views → Hold Rate → ThruPlays

Account Type → Primary Conversion Metric (PCM)

Read promoted_object.custom_event_type from the ad set (facebook_get_details_of_ad_account returns it for top spenders; otherwise facebook_get_adset_details). NEVER infer from campaign or ad set names.

custom_event_typeAccount TypePCM
PURCHASEE-commercePurchase ROAS
LEADLead GenerationCost Per Lead
COMPLETE_REGISTRATIONRegistrationCost Per Registration
OTHER + custom_event_strCustom ConversionCost Per Result for that specific event

If promoted_object is missing → ASK the user. Never assume. Mixed accounts: group ad sets by custom_event_type and apply each group's PCM separately.

Performance Benchmarks

MetricGoodAveragePoor
Hook Rate≥ 40%26–39%< 25%
Hold Rate> Account Avg + 25%≈ Account Avg< Account Avg
CTR≥ 1.25%0.65 – 1.24%< 0.65%
CPM variance vs Pareto avg≤ 20%20 – 60%> 60%
PCM variance vs Pareto avgAbove avg± 20%> 30% below
Budget utilization≥ 85%—< 85%
Min ad-set spend share for comparison≥ 25% of campaign——

For Hold Rate, compute account_avg_hold_rate from a 90-day account-level pull (facebook_get_adaccount_insights at level="account" with date_preset="last_90d" and the video fields) before applying.

Diagnostic Signals (definitions only — workflow lives in meta-depth-of-analysis)

SignalMeans
Frequency rising AND CTR falling over 14+ daysCreative fatigue
CBO with one ad set holding 80%+ of budgetAlgorithm working as intended — do NOT pause the dominant ad set on small-sample noise
High frequency alone (no CTR drop)Not fatigue
Cost cap + rising CPMEither delivery squeeze or audience saturation — separate before acting

Statistical Significance Floors

DecisionMinimum signal
Per-ad-set performance judgment3–5 conversions / week
Per-segment recommendation (placement, age, device)≥ 100 impressions AND ≥ 3 conversions
Pause ad on high CPA≥ 3 conversions if non-zero, OR spend ≥ 2× ad-set CPA target if zero
Ad set learning phase exitSpend ≥ 2× AOV OR 4× CPA, whichever is higher

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.