When you review a competitor's ad, you ask the same questions every time. What's the hook? Who is it for? What's the offer? What does it ask you to do? The ad-breakdown preset answers them as fields, and every answer comes with the words in the ad that back it.
It works on TikToks, Instagram reels and YouTube videos. Paste a link in the playground, or call the API.
An example #
Glossier's 15-second Lip Glaze TikTok, which TikTok marks as an ad:
curl https://api.cleanscript.ai/v1/extract \
-H "Authorization: Bearer $CLEANSCRIPT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.tiktok.com/@glossier/video/7502838645104086314", "preset": "ad-breakdown"}'{
"data": {
"hook": "Creamy. Chilly.",
"hook_type": "other",
"angle": "A creamy, cooling lip oil offers a sheer glaze finish and lasting nourishment.",
"audience": null,
"product": { "name": "Lip Glaze", "brand": "Glossier" },
"offer": null,
"claims": [
"Lip Glaze is a creamy, cooling lip oil.",
"It has a sheer glaze finish.",
"It provides lasting nourishment.",
"It launches on 5/20 at Glossier and Sephora with KATSEYE."
],
"cta": "Join the list at the link in bio to be notified when Lip Glaze drops.",
"tone": "Playful and sensory"
},
"citations": {
"hook": [{ "quote": "Creamy. Chilly.", "source": "speech", "start": 0.0, "end": 3.0, "url": "https://www.tiktok.com/@glossier/video/7502838645104086314" }],
"cta": [{ "quote": "Join the list at the link in bio to be notified when it drops.", "source": "description", "start": null, "end": null, "url": null }]
}
}Shortened. The full response also has pain_points, promise, proof, objections_handled and structure, the ad's stages in order.
How to read it:
- The hook is copied word for word from the first seconds. It's a run of sensory words, so
hook_typeisother. The types arequestion,bold_claim,problem,story,demonstration,statistic,curiosity,news,offerandother. offerisnullbecause the ad names no price, discount or code.- The call to action comes from the caption, not the speech. Each citation's
sourcesays where its words are: spoken (speech), written in the post (description,title) or shown on screen (on_screen). audienceisnullbecause the ad never says who it's for.
This one is a launch teaser, so it fills little. An ad with a price, a code and a promise fills far more.
Build a swipe file #
Put your ad links in a text file, one per line, and write one row per ad:
# pip install cleanscript-ai
import csv
from cleanscript_ai import CleanScript
client = CleanScript()
urls = open("ads.txt").read().split()
with open("swipe-file.csv", "w", newline="") as f:
out = csv.writer(f)
out.writerow(["url", "hook", "hook_type", "offer", "cta"])
for url in urls:
data = client.extract(url, preset="ad-breakdown").data
out.writerow([url, data["hook"], data["hook_type"], data["offer"], data["cta"]])Open the CSV in a spreadsheet and sort by hook_type to see which techniques your competitors lean on. To choose which posts to read, start from a brand's most and least viewed: find what a competitor's top videos have in common.
An ad under 10 minutes costs 3 credits, its transcript included. See pricing.
Different questions on the same ad #
A prompt next to the preset adds guidance, such as "focus on the sponsor segment" for a YouTube video with a mid-roll ad. For fields the preset doesn't have, send your own JSON Schema.
Limits #
- The breakdown reads what is said and the post's text, and the text shown on screen when nobody speaks. It doesn't describe images, so an ad told only in pictures and music gets thin results.
- Any field the ad doesn't address is
null.
Spot something wrong? Tell us.