Back to Blog
Strategy

Competitor Swipe File: Automate Creative & Copy Collection from Social Media

May 9, 2026
6 min read
S
By SociaVault Team
Competitor AnalysisSwipe FileCreative AnalysisAd LibraryAPI

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:

CategoryWhat to CollectWhy
HooksFirst lines of top postsLearn what stops the scroll
CTAsCalls-to-action that drive actionTest proven CTAs
Social proofTestimonials, numbers, logosBorrow credibility patterns
Visual stylesColor palettes, layouts, formatsInspire your own creative
Ad copyHeadlines, descriptions, offersSee what they're paying for
Content formatsCarousel vs reel vs staticKnow what format works
Hashtag strategiesTag sets on top contentFind community tags

Automation Schedule

Run your swipe file collector on a schedule:

FrequencyWhat to CollectWhy
WeeklyTop organic posts (IG, TikTok, Twitter)Stay current on content trends
Bi-weeklyAd library snapshotsTrack messaging pivots
MonthlyFull competitor auditBig-picture strategy review
QuarterlyCross-competitor pattern analysisIdentify industry-wide shifts

Get Started

Sign up free — start building an automated competitor swipe file with real data.


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.