How to Automate Ad Compliance and Policy Checks
Pre-screen ads for policy violations before submission to reduce rejections.
Jay Banlasan
The AI Systems Guy
Getting an ad rejected on Meta after a campaign launch is one of the most avoidable problems in paid advertising. The rejection kills delivery, the ad enters review again, and you lose hours of momentum during a launch window. Building an automate ad compliance policy check review system into my creative workflow stopped 90% of rejections before they happened. The AI screens every ad against platform policies before I submit anything.
This matters beyond the obvious time savings. Repeated policy rejections flag your ad account. Enough of them and you're looking at account-level restrictions. A pre-submission compliance check is cheap insurance against that outcome.
What You Need Before Starting
- Python 3.10+
anthropicSDK- The Meta Advertising Policies document (download as PDF or text from Meta Business Help Center)
- A list of your own industry-specific restricted terms (medical claims, financial guarantees, etc.)
- The ad copy and creative briefs you want to screen
Step 1: Build Your Policy Rule Set
Start with the most commonly violated policies. You don't need to encode everything — focus on the rules that cause 80% of rejections.
from dataclasses import dataclass, field
@dataclass
class PolicyRule:
id: str
platform: str # "meta", "google", "tiktok"
category: str
description: str
forbidden_patterns: list[str] # exact strings to flag
risk_level: str # "hard_block", "warning", "review"
example_violation: str
example_compliant: str
META_POLICIES = [
PolicyRule(
id="meta_personal_attributes",
platform="meta",
category="Personal Attributes",
description="Cannot imply knowledge of personal characteristics",
forbidden_patterns=[
"are you struggling with", "do you have diabetes",
"if you're overweight", "do you suffer from",
"you have anxiety", "you're going through a divorce"
],
risk_level="hard_block",
example_violation="Are you struggling with debt?",
example_compliant="Debt solutions for people who want a fresh start"
),
PolicyRule(
id="meta_misleading_claims",
platform="meta",
category="Misleading Claims",
description="No guaranteed results or exaggerated claims",
forbidden_patterns=[
"guaranteed results", "100% success",
"you will lose", "proven to cure",
"miracle", "instant results",
"make $10,000 in your first week"
],
risk_level="hard_block",
example_violation="Guaranteed to lose 20lbs in 2 weeks",
example_compliant="Clients average 8lbs lost in their first month"
),
PolicyRule(
id="meta_before_after",
platform="meta",
category="Health Claims",
description="Before/after imagery in health/weight loss ads restricted",
forbidden_patterns=[
"before and after", "before & after",
"transformation tuesday", "look at my results"
],
risk_level="warning",
example_violation="See my before and after transformation",
example_compliant="See how our program helped Sarah reach her goals"
),
PolicyRule(
id="meta_financial_guarantees",
platform="meta",
category="Financial Products",
description="Cannot guarantee investment returns",
forbidden_patterns=[
"guaranteed return", "risk-free investment",
"you will make money", "no risk",
"can't lose"
],
risk_level="hard_block",
example_violation="Risk-free investment with guaranteed 20% returns",
example_compliant="Investment strategies for long-term wealth building"
),
PolicyRule(
id="meta_adult_content",
platform="meta",
category="Adult Content",
description="Sexual content and excessive skin not permitted in general placements",
forbidden_patterns=[
"sexy", "hot singles", "find a date tonight",
"hookup", "explicit"
],
risk_level="hard_block",
example_violation="Find sexy singles near you tonight",
example_compliant="Meet new people in your area"
),
]
Step 2: Build the Rule-Based Pre-Screen
Fast pattern matching runs first. No API calls needed for obvious violations.
import re
def rule_based_check(ad_copy: str, platform: str = "meta") -> list[dict]:
violations = []
copy_lower = ad_copy.lower()
rules = [r for r in META_POLICIES if r.platform == platform]
for rule in rules:
for pattern in rule.forbidden_patterns:
if pattern.lower() in copy_lower:
violations.append({
"rule_id": rule.id,
"category": rule.category,
"risk": rule.risk_level,
"trigger": pattern,
"description": rule.description,
"fix": f"Example of compliant copy: {rule.example_compliant}"
})
break # one violation per rule is enough
return violations
Step 3: Build the AI Policy Reviewer
The AI catches nuanced violations that pattern matching misses — implied personal attributes, borderline medical claims, misleading framing that doesn't use banned keywords.
import anthropic
import json
_client = anthropic.Anthropic()
POLICY_SUMMARY = """
META ADVERTISING POLICIES SUMMARY (Key Rules):
1. Personal Attributes: Never directly address or imply knowledge of personal
characteristics like health conditions, finances, relationship status, or identity.
BAD: "Are you struggling with debt?" GOOD: "Debt solutions that actually work"
2. Misleading Claims: No guaranteed results, miracle cures, or exaggerated claims
without substantiation. All income claims need qualification.
BAD: "Guaranteed to lose 20lbs" GOOD: "Clients average 8lbs in month one"
3. Health/Medical: No claims of curing diseases. Weight loss ads cannot use
before/after imagery or imply impossible/dangerous results.
4. Financial: No guaranteed investment returns or risk-free claims.
5. Adult/Sensitive: No sexual content, shock content, or graphic images.
6. Discrimination: Ads cannot discriminate on protected characteristics.
7. Engagement Bait: No "like this if", "tag a friend who", vote baiting.
"""
def ai_policy_review(ad_copy: str, headline: str = "",
platform: str = "meta") -> dict:
prompt = f"""You are a Meta Ads compliance expert. Review this ad for policy violations.
{POLICY_SUMMARY}
Ad to review:
Headline: {headline}
Body Copy: {ad_copy}
Return JSON only:
{{
"approved": true/false,
"risk_level": "safe|warning|likely_rejected",
"violations": [
{{"rule": "rule name", "issue": "specific problem", "fix": "how to rewrite"}}
],
"overall_assessment": "one sentence"
}}"""
response = _client.messages.create(
model="claude-haiku-3", max_tokens=600,
messages=[{"role": "user", "content": prompt}]
)
try:
return json.loads(response.content[0].text.strip())
except json.JSONDecodeError:
return {"approved": None, "risk_level": "review",
"violations": [], "overall_assessment": "Review manually"}
Step 4: Build the Combined Compliance Checker
Combine rule-based and AI checks into one function that returns a final verdict.
@dataclass
class ComplianceResult:
approved: bool
risk_level: str # "safe", "warning", "likely_rejected", "blocked"
violations: list[dict]
suggestions: list[str]
confidence: float
def check_ad_compliance(
headline: str,
body_copy: str,
platform: str = "meta"
) -> ComplianceResult:
full_copy = f"{headline} {body_copy}"
# Stage 1: Rule-based check
rule_violations = rule_based_check(full_copy, platform)
hard_blocks = [v for v in rule_violations if v["risk"] == "hard_block"]
if hard_blocks:
return ComplianceResult(
approved=False,
risk_level="blocked",
violations=rule_violations,
suggestions=[v["fix"] for v in hard_blocks],
confidence=0.99
)
# Stage 2: AI review for nuanced issues
ai_result = ai_policy_review(body_copy, headline, platform)
all_violations = rule_violations + ai_result.get("violations", [])
risk = ai_result.get("risk_level", "safe")
return ComplianceResult(
approved=risk == "safe" and not hard_blocks,
risk_level=risk,
violations=all_violations,
suggestions=[v.get("fix","") for v in ai_result.get("violations",[])],
confidence=0.85 if ai_result.get("approved") is not None else 0.5
)
Step 5: Build a Batch Screener for Creative Reviews
Screen multiple ad variants before a campaign launch.
def screen_creative_batch(ads: list[dict]) -> list[dict]:
"""
ads = list of {"id": str, "headline": str, "copy": str}
"""
results = []
for ad in ads:
result = check_ad_compliance(
headline=ad.get("headline", ""),
body_copy=ad.get("copy", "")
)
results.append({
"id": ad["id"],
"approved": result.approved,
"risk": result.risk_level,
"violations": result.violations,
"suggestions":result.suggestions
})
print(f"Ad {ad['id']}: {result.risk_level.upper()} — "
f"{len(result.violations)} violation(s)")
approved = sum(1 for r in results if r["approved"])
print(f"\n{approved}/{len(ads)} ads cleared for submission")
return results
Step 6: Generate a Compliant Rewrite for Flagged Ads
When an ad fails, give the copywriter a compliant version to work from, not just a list of problems.
def rewrite_for_compliance(headline: str, body_copy: str,
violations: list[dict]) -> dict:
issues = "\n".join(f"- {v['rule']}: {v['issue']}" for v in violations[:3])
prompt = f"""Rewrite this ad to comply with Meta's advertising policies.
Original headline: {headline}
Original copy: {body_copy}
Issues to fix:
{issues}
Rules:
- Keep the same core offer and message
- Fix the specific policy violations
- Maintain persuasive language and emotional appeal
- Do not add fake claims or guarantees
Return JSON:
{{"headline": "rewritten headline", "copy": "rewritten body copy",
"what_changed": "brief explanation of changes"}}"""
response = _client.messages.create(
model="claude-sonnet-4-5", max_tokens=400,
messages=[{"role": "user", "content": prompt}]
)
try:
return json.loads(response.content[0].text.strip())
except Exception:
return {"headline": headline, "copy": body_copy, "what_changed": "Review manually"}
What to Build Next
- Add Google Ads and TikTok Ads policy rules to screen across all your active platforms in one pass
- Build a compliance history log that tracks which violations appear most often so you can update your creative brief templates
- Integrate the compliance checker into your creative brief template so it runs automatically before briefs are approved for production
Related Reading
- How to Automate Daily Meta Ads Reporting - compliance checks reduce rejections that would otherwise distort your reporting
- How to Build an AI Ad Headline Generator - generate headlines that are compliant from the start
- How to Automate Ad Account Health Monitoring - account health monitoring catches the downstream effects of policy violations
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment