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.
In this repository61 other files it gives its agents.
- access-and-permissionsSkill
- accounts-and-connectionsSkill
- ad-brief-generatorSkill
- affiliate-marketingSkill
- analyse-creativeSkill
- automate-with-agentsSkill
- brief-creativeSkill
- build-reportsSkill
- clean-wasted-spendSkill
- competitor-ad-intelligenceSkill
- creative-psychology-hooksSkill
- creative-researchSkill
- diagnose-performanceSkill
- email-marketingSkill
- ga4-source-of-truthSkill
- get-startedSkill
- gomarble-skills-creative-strategistsSkill
- gomarble-skills-ecommerce-brandsSkill
- gomarble-skills-google-ads-auditSkill
- gomarble-skills-meta-ads-auditSkill
- gomarble-skills-saas-companiesSkill
- google-ads-create-master-skillSkill
- google-ads-depth-of-analysisSkill
- google-ads-guardrailsSkill
- google-ads-keywordplannerSkill
- google-ads-pmax-evaluationSkill
- google-ads-pmax-scalingSkill
- google-ads-search-analysisSkill
- google-ads-search-executionSkill
- google-ads-shoppingSkill
- google-ads-tool-fundamentalsSkill
- google-impression-shareSkill
- google-pmax-pulseSkill
- google-search-auditSkill
- google-search-term-auditSkill
- launch-campaignsSkill
- linkedin-adsSkill
- manage-campaignsSkill
- meta-ads-auditSkill
- meta-agent-operationsSkill
- meta-create-master-skillSkill
- meta-creative-analysisSkill
- meta-creative-fatigue-detectionSkill
- meta-creative-strategySkill
- meta-custom-event-interpretationSkill
- meta-daily-optimizationSkill
- meta-depth-of-analysisSkill
- meta-guardrailsSkill
- meta-performance-analysisSkill
- microsoft-adsSkill
- organic-socialSkill
- own-creative-diagnosisSkill
- research-competitorsSkill
- search-console-master-skillSkill
- shift-budgetSkill
- shopify-order-disciplineSkill
- tiktok-adsSkill
- tiktok-create-master-skillSkill
- winning-ads-engineSkill
- winning-ads-orchestratorSkill
- The first 60 shown.
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
- Very specific: line 28
Default filtering: Always apply filtering=[{"field":"impressions","operator":"GREATER_THAN","value":0}] unless user wants non-delivered …
- Very specific: line 30
Active entity filtering (CRITICAL): When analyzing current performance, ALWAYS add an effective_status filter to exclude paused/deleted …
- Very specific: line 37
Only omit the effective_status filter when the user explicitly asks for historical or paused entity data.
- Very specific: line 39
Default sorting: Use sort='spend_descending' unless user specifies otherwise.
- Very specific: line 41
Breakdowns: Only include when specifically requested.
- Very specific: line 43
Creative fatigue analysis: Use time_increment='1' for daily trend data.
- Very specific: line 51
Rule: Use ONLY ONE. Check omni_purchase first.
- Distinctive: line 56
Before using Meta insights data for totals, rankings, CPA/ROAS, budget allocation, campaign comparisons, or Python/advanced analysis:
- Very specific: line 57
Call facebook_fetch_pagination_url with the exact paging.next URL.
- Distinctive: line 59
Only then combine pages and analyze.
- Distinctive: line 61
Never present totals or conclusions from a partial Meta insights page.
- Very specific: line 64
ALL Meta propose tools — facebook_propose_create_campaign_structure AND every facebook_propose_update_* tool — take budgets/bids in ACCOUNT …
- Very specific: line 66
Only Meta's RAW response fields — insights and account_structure budget fields — are in cents ($50 = 5000): divide those by 100 when …
- Very specific: line 69
Always call facebook_get_details_of_ad_account first.
- Distinctive: line 72
Use this to find entity IDs and understand what's running before deeper analysis
- Very specific: line 75
If facebook_get_adaccount_insights fails with "reduce the amount of data", use facebook_get_async_adaccount_insights instead.
- Very specific: line 82
Use CONTAIN/NOT_CONTAIN for text, GREATER_THAN/LESS_THAN for numbers, IN/NOT_IN for multiple values
- Very specific: line 146
Read promoted_object.custom_event_type from the ad set (facebook_get_details_of_ad_account returns it for top spenders.
- Very specific: line 155
If promoted_object is missing → ASK the user.
≈ “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.
Files
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 metricscampaign— compare campaign performanceadset— analyze targeting/audience performancead— 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_namematching 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:
- Call
facebook_fetch_pagination_urlwith the exactpaging.nextURL. - Continue fetching until the latest response has no
paging.nextand the data-quality block saysresponse_complete=true. - 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_structurewith 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_CONTAINfor text,GREATER_THAN/LESS_THANfor numbers,IN/NOT_INfor 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)
| Metric | API Field | How to Extract |
| Spend | spend | Direct |
| CPM | cpm | Direct |
| CTR | ctr | Direct |
| Impressions | impressions | Direct |
| Clicks | clicks | Direct |
| Reach | reach | Direct |
| Frequency | frequency | Direct |
| Video Plays | video_play_actions[0].value | Initial impressions of the video |
| 3-Second Views | actions array, action_type=video_view | Hook engagement — NOT a separate field |
| ThruPlays | video_thruplay_watched_actions[0].value | 15s+ watch or completion |
| Purchases | actions array, action_type=omni_purchase (fallback purchase) | Use ONE only — see Purchase De-Duplication |
| Leads | actions array, action_type=lead | |
| Revenue | action_values array, action_type=omni_purchase | |
| Purchase ROAS | purchase_roas | Direct |
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
| Metric | Formula | Notes |
| Hook Rate | (3-sec views / video plays) * 100 | Uses actions[video_view], NOT video_p25_watched_actions |
| Hold Rate | (thruplays / 3-sec views) * 100 | |
| Cost Per Purchase | spend / actions[purchase].value | |
| Cost Per Lead (CPL) | spend / actions[lead].value | |
| Cost Per Result (CPR) | spend / actions[<custom_event>].value | Use the SPECIFIC custom_event_str — never conversions totals |
| Conversion Rate (CVR) | actions[<event>].value / clicks * 100 | |
| Budget Utilization | spend / (daily_budget * days_in_period) | Daily budget is in cents |
| Campaign Spend Share | entity_spend / parent_total_spend | For ad-set comparison; require ≥ 25% before comparing |
| Pareto Set | Sort 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 → ThruPlaysAccount 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_type | Account Type | PCM |
PURCHASE | E-commerce | Purchase ROAS |
LEAD | Lead Generation | Cost Per Lead |
COMPLETE_REGISTRATION | Registration | Cost Per Registration |
OTHER + custom_event_str | Custom Conversion | Cost 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
| Metric | Good | Average | Poor |
| 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 avg | Above 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)
| Signal | Means |
| Frequency rising AND CTR falling over 14+ days | Creative fatigue |
| CBO with one ad set holding 80%+ of budget | Algorithm 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 CPM | Either delivery squeeze or audience saturation — separate before acting |
Statistical Significance Floors
| Decision | Minimum signal |
| Per-ad-set performance judgment | 3–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 exit | Spend ≥ 2× AOV OR 4× CPA, whichever is higher |
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
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.

