Competitor Swipe File: Automate Creative & Copy Collection from Social Media
Every marketer keeps a swipe file ā a collection of ads, posts, and copy that inspired them. Most do it manually: screenshots saved in random folders, bookmarks that expire, links they'll never find again.
Here's how to automate it with data, so your swipe file stays current and organized.
Collect Top-Performing Competitor Posts
Pull top content from competitors automatically:
const API_KEY = process.env.SOCIAVAULT_API_KEY;
const BASE = 'https://api.sociavault.com/v1/scrape';
const headers = { 'X-API-Key': API_KEY };
async function buildSwipeFile(competitors) {
const swipeFile = [];
for (const competitor of competitors) {
// Instagram top posts
if (competitor.instagram) {
const res = await fetch(
`${BASE}/instagram/posts?username=${encodeURIComponent(competitor.instagram)}`,
{ headers }
);
const posts = (await res.json()).data || [];
const sorted = posts.sort((a, b) => (b.like_count || 0) - (a.like_count || 0));
for (const post of sorted.slice(0, 5)) {
swipeFile.push({
competitor: competitor.name,
platform: 'Instagram',
type: post.product_type === 'clips' ? 'Reel'
: post.carousel_media ? 'Carousel' : 'Image',
caption: (post.caption?.text || '').slice(0, 300),
likes: post.like_count || 0,
comments: post.comment_count || 0,
url: `https://instagram.com/p/${post.shortcode || ''}`,
tags: extractHashtags(post.caption?.text || '')
});
}
await new Promise(r => setTimeout(r, 1200));
}
// TikTok top videos
if (competitor.tiktok) {
const res = await fetch(
`${BASE}/tiktok/user/posts?username=${encodeURIComponent(competitor.tiktok)}`,
{ headers }
);
const videos = (await res.json()).data || [];
const sorted = videos.sort((a, b) =>
((b.stats?.playCount) || 0) - ((a.stats?.playCount) || 0)
);
for (const v of sorted.slice(0, 5)) {
swipeFile.push({
competitor: competitor.name,
platform: 'TikTok',
type: 'Video',
caption: (v.desc || '').slice(0, 300),
views: v.stats?.playCount || 0,
likes: v.stats?.diggCount || 0,
comments: v.stats?.commentCount || 0,
shares: v.stats?.shareCount || 0,
duration: v.video?.duration || 0,
tags: extractHashtags(v.desc || '')
});
}
await new Promise(r => setTimeout(r, 1200));
}
// Twitter/X top tweets
if (competitor.twitter) {
const res = await fetch(
`${BASE}/twitter/user-tweets?username=${encodeURIComponent(competitor.twitter)}`,
{ headers }
);
const tweets = (await res.json()).data || [];
const sorted = tweets.sort((a, b) =>
((b.legacy?.favorite_count) || 0) - ((a.legacy?.favorite_count) || 0)
);
for (const t of sorted.slice(0, 5)) {
swipeFile.push({
competitor: competitor.name,
platform: 'Twitter/X',
type: 'Tweet',
caption: (t.legacy?.full_text || '').slice(0, 300),
likes: t.legacy?.favorite_count || 0,
retweets: t.legacy?.retweet_count || 0,
tags: extractHashtags(t.legacy?.full_text || '')
});
}
await new Promise(r => setTimeout(r, 1200));
}
}
// Sort by engagement
swipeFile.sort((a, b) => (b.likes || 0) - (a.likes || 0));
console.log(`\nš Competitor Swipe File (${swipeFile.length} entries)`);
console.log('ā'.repeat(60));
swipeFile.forEach((entry, i) => {
console.log(`\n ${i + 1}. [${entry.platform}] ${entry.competitor} - ${entry.type}`);
console.log(` ${entry.caption.slice(0, 120)}...`);
console.log(` Likes: ${(entry.likes || 0).toLocaleString()} | Comments: ${(entry.comments || 0).toLocaleString()}`);
if (entry.views) console.log(` Views: ${entry.views.toLocaleString()}`);
if (entry.tags.length) console.log(` Tags: ${entry.tags.join(' ')}`);
});
return swipeFile;
}
function extractHashtags(text) {
return (text.match(/#\w+/g) || []).slice(0, 5);
}
buildSwipeFile([
{ name: 'Notion', instagram: 'notionhq', tiktok: 'notionhq', twitter: 'NotionHQ' },
{ name: 'Figma', instagram: 'figma', tiktok: 'figma', twitter: 'figma' },
{ name: 'Canva', instagram: 'canva', tiktok: 'canva', twitter: 'canva' }
]);
Scrape Competitor Ads from Ad Libraries
See what competitors are actually spending money on:
import os
import time
import requests
API_KEY = os.environ["SOCIAVAULT_API_KEY"]
BASE = "https://api.sociavault.com/v1/scrape"
HEADERS = {"X-API-Key": API_KEY}
def collect_competitor_ads(competitors):
"""Build a swipe file from Facebook and Google ad libraries"""
ad_swipe = []
for competitor in competitors:
# Facebook Ad Library
r = requests.get(f"{BASE}/facebook-ad-library", headers=HEADERS,
params={"query": competitor["name"]})
fb_ads = r.json().get("data", [])
for ad in fb_ads[:10]:
ad_swipe.append({
"competitor": competitor["name"],
"platform": "Facebook/Instagram",
"headline": ad.get("ad_creative_bodies", [""])[0][:200] if ad.get("ad_creative_bodies") else "",
"cta": ad.get("ad_creative_link_captions", [""])[0] if ad.get("ad_creative_link_captions") else "",
"status": ad.get("ad_delivery_status", "unknown"),
"started": ad.get("ad_delivery_start_time", "N/A"),
"page": ad.get("page_name", "N/A")
})
time.sleep(1.5)
# Google Ad Library
r = requests.get(f"{BASE}/google-ad-library", headers=HEADERS,
params={"query": competitor["name"]})
google_ads = r.json().get("data", [])
for ad in google_ads[:10]:
ad_swipe.append({
"competitor": competitor["name"],
"platform": "Google",
"headline": ad.get("headline", "")[:200],
"description": ad.get("description", "")[:200],
"format": ad.get("format", "unknown"),
"advertiser": ad.get("advertiser_name", "N/A")
})
time.sleep(1.5)
# Print
print(f"\nš¢ Ad Swipe File ({len(ad_swipe)} ads)")
print("=" * 55)
for i, ad in enumerate(ad_swipe, 1):
print(f"\n {i}. [{ad['platform']}] {ad['competitor']}")
if ad.get("headline"):
print(f" Copy: \"{ad['headline'][:120]}\"")
if ad.get("cta"):
print(f" CTA: {ad['cta']}")
if ad.get("description"):
print(f" Desc: \"{ad['description'][:120]}\"")
return ad_swipe
collect_competitor_ads([
{"name": "Monday.com"},
{"name": "Asana"},
{"name": "ClickUp"}
])
Analyze Copy Patterns
Find what messaging patterns your competitors use most:
async function analyzeCopyPatterns(swipeFile) {
// Common copy frameworks
const frameworks = {
'Problem-Agitate-Solution': [
/tired of|struggling with|frustrated|sick of/i,
/instead of|but what if|imagine/i,
/introducing|try|discover|get started/i
],
'Social Proof': [
/\d+[kKmM\+]?\s*(users|customers|companies|brands|teams)/i,
/trusted by|used by|loved by|rated/i
],
'FOMO/Urgency': [
/limited|last chance|ending soon|don't miss|only \d+/i,
/while supplies|act now|today only/i
],
'Question Hook': [
/^(did you know|have you|what if|why do|how to|want to)/i
],
'Listicle/Number': [
/\d+\s*(ways|tips|reasons|steps|mistakes|secrets|hacks)/i
],
'Comparison': [
/vs\.?|versus|compared to|better than|unlike/i
]
};
const patternCounts = {};
Object.keys(frameworks).forEach(f => patternCounts[f] = { count: 0, examples: [] });
for (const entry of swipeFile) {
const text = entry.caption || '';
for (const [framework, patterns] of Object.entries(frameworks)) {
for (const pattern of patterns) {
if (pattern.test(text)) {
patternCounts[framework].count++;
if (patternCounts[framework].examples.length < 3) {
patternCounts[framework].examples.push({
competitor: entry.competitor,
text: text.slice(0, 100)
});
}
break;
}
}
}
}
console.log('\nāļø Copy Pattern Analysis');
console.log('ā'.repeat(55));
const sorted = Object.entries(patternCounts).sort((a, b) => b[1].count - a[1].count);
sorted.forEach(([framework, data]) => {
const pct = swipeFile.length > 0 ? Math.round(data.count / swipeFile.length * 100) : 0;
console.log(`\n ${framework}: ${data.count} uses (${pct}%)`);
data.examples.forEach(ex =>
console.log(` "${ex.text}..." ā ${ex.competitor}`)
);
});
return patternCounts;
}
Swipe File Categories
Organize your swipe file by intent:
| Category | What to Collect | Why |
|---|---|---|
| Hooks | First lines of top posts | Learn what stops the scroll |
| CTAs | Calls-to-action that drive action | Test proven CTAs |
| Social proof | Testimonials, numbers, logos | Borrow credibility patterns |
| Visual styles | Color palettes, layouts, formats | Inspire your own creative |
| Ad copy | Headlines, descriptions, offers | See what they're paying for |
| Content formats | Carousel vs reel vs static | Know what format works |
| Hashtag strategies | Tag sets on top content | Find community tags |
Automation Schedule
Run your swipe file collector on a schedule:
| Frequency | What to Collect | Why |
|---|---|---|
| Weekly | Top organic posts (IG, TikTok, Twitter) | Stay current on content trends |
| Bi-weekly | Ad library snapshots | Track messaging pivots |
| Monthly | Full competitor audit | Big-picture strategy review |
| Quarterly | Cross-competitor pattern analysis | Identify industry-wide shifts |
Get Started
Sign up free ā start building an automated competitor swipe file with real data.
Related Reading
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API. No credit card required.