.claude/skills/gtm-analytics/SKILL.md
Pull cross-channel GTM performance data from Meta Ads, Instagram, Pinterest, Blog, GA4, and Search Console — generate a unified report with analysis and recommendations.
npx skillsauth add Abhi5415/clarido-marketing gtm-analyticsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Cross-channel performance report for Clarido's go-to-market: Meta Ads, Instagram, Pinterest, Blog, GA4, and Search Console. Invoked with /gtm-analytics.
| Channel | Method | Script / Tool | Output |
|---------|--------|---------------|--------|
| Meta Ads | Python API script | scripts/analytics/pull_meta_ads.py | Campaigns, ads, boosted posts, demographics |
| Instagram | Python API script | scripts/analytics/pull_instagram_insights.py | Media items with engagement rates, boost flags |
| GA4 | Python API script | scripts/analytics/pull_ga4.py | Sessions, pageviews, traffic sources |
| Search Console | Python API script | scripts/analytics/pull_search_console.py | Clicks, impressions, queries, page performance |
| Pinterest | Chrome + JavaScript | Pinterest Analytics (browser automation) | Account metrics, pin performance |
| Blog | Inline (curl + file read) | Health check + GSC cross-reference | Article status, SEO performance per article |
| Report | Python aggregator | scripts/analytics/generate_report.py | Unified markdown report |
All intermediate data goes to tmp/analytics/*.json. Final report: reports/gtm/YYYY-MM-DD.md (one file per day, never overwritten).
Run all 5 scripts. If any fail (token issues, API errors), note the error and continue.
mkdir -p tmp/analyticspipenv run python3 scripts/analytics/pull_meta_ads.py --days 30
pipenv run python3 scripts/analytics/pull_instagram_insights.py --days 30
engagement_rate and boosted flagpipenv run python3 scripts/analytics/pull_search_console.py --days 30
pipenv run python3 scripts/analytics/pull_ga4.py --days 30
507996912 (owned by [email protected]). Service account has Viewer access.Create a new tab and navigate to https://analytics.pinterest.com/
https://www.pinterest.com/business/hub/ insteadWait for the analytics dashboard to load (3-5 seconds)
Run JavaScript to extract account-level metrics:
// Extract Pinterest Analytics dashboard data
(() => {
const metrics = {};
// Look for metric cards on the analytics dashboard
const cards = document.querySelectorAll('[class*="metric"], [class*="Metric"], [class*="stat"], [class*="Stat"], [data-test*="metric"]');
cards.forEach(card => {
const label = card.querySelector('[class*="label"], [class*="Label"], [class*="title"]')?.textContent?.trim()?.toLowerCase();
const value = card.querySelector('[class*="value"], [class*="Value"], [class*="number"]')?.textContent?.trim();
if (label && value) metrics[label] = value;
});
// Fallback: parse visible text for known Pinterest metrics
if (Object.keys(metrics).length === 0) {
const text = document.body.innerText;
const patterns = {
impressions: /impressions[:\s]*([0-9,]+)/i,
engagements: /(?:engagements|total engagement)[:\s]*([0-9,]+)/i,
pin_clicks: /(?:pin clicks|closeups)[:\s]*([0-9,]+)/i,
outbound_clicks: /(?:outbound clicks|link clicks)[:\s]*([0-9,]+)/i,
saves: /(?:saves)[:\s]*([0-9,]+)/i,
};
for (const [key, pattern] of Object.entries(patterns)) {
const match = text.match(pattern);
if (match) metrics[key] = match[1];
}
}
// Try to find top pins table
const pins = [];
const pinRows = document.querySelectorAll('[class*="pin-row"], [class*="PinRow"], table tbody tr, [class*="top-pin"]');
pinRows.forEach(row => {
const title = row.querySelector('[class*="title"], [class*="pin-name"], img')?.getAttribute('alt') || row.querySelector('[class*="title"]')?.textContent?.trim();
const impressions = row.querySelectorAll('[class*="value"], td')[0]?.textContent?.trim();
const saves = row.querySelectorAll('[class*="value"], td')[1]?.textContent?.trim();
if (title) pins.push({ title, impressions, saves });
});
return JSON.stringify({ metrics, pins, url: window.location.href });
})()
If account-level data is available, navigate to individual pin analytics pages if needed.
Write results to tmp/analytics/pinterest.json:
{
"source": "pinterest",
"pulled_at": "2026-02-23T...",
"account": {
"impressions": 150,
"saves": 3,
"pin_clicks": 5,
"outbound_clicks": 2
},
"pins": [
{
"title": "Brain Dump Before Bed",
"metrics": { "impressions": 50, "saves": 1, "pin_clicks": 2, "outbound_clicks": 1 }
}
]
}
No script needed. Do this inline:
~/dev/clarido-landing-page/content/blog/*.md files — extract frontmatter (title, slug, date, tags)curl -s -o /dev/null -w "%{http_code}" https://clarido.app/blog/{slug}top_pages data from tmp/analytics/search_console.json:
blog.json with GSC clicks/impressions per articletmp/analytics/blog.json:{
"source": "blog",
"pulled_at": "2026-03-02T...",
"articles": [
{
"title": "Why Brain Dumping Works",
"slug": "brain-dumping-article",
"date": "2026-02-19",
"url": "https://clarido.app/blog/brain-dumping-article",
"live": true,
"gsc_clicks": 5,
"gsc_impressions": 40
}
],
"total_articles": 4
}
pipenv run python3 scripts/analytics/generate_report.pytmp/analytics/ and produces reports/gtm/YYYY-MM-DD.mdAfter the report is generated, read both reports/gtm/YYYY-MM-DD.md and docs/content-strategy.md, then provide opinionated analysis:
The report's "What To Do Today" section now includes a Current Status table (followers, posts this week, channel phase, target frequency) and automated action items based on the content strategy rules. Use this as a starting point, then layer on:
After the AI analysis, email the update to both [email protected] and [email protected]. This is NOT optional — always send the email at the end of every run.
[email protected] (use as user_google_email)[email protected]Clarido GTM Update — {YYYY-MM-DD}reports/gtm/{YYYY-MM-DD}.md in the repoKeep it short enough to read in 30 seconds on a phone. No markdown tables in the email — use plain text with dashes or line breaks. No attachments.
Pinterest Analytics changes its DOM structure frequently. The JavaScript snippets above use multiple selector strategies (class patterns, fallback regex on page text) to be resilient. If they return empty data:
read_page to see the current page structureread_page with filter: "text" as a last resort to get all visible text and parse it manuallypipenv run python3 scripts/pinterest/refresh_token.pyGOOGLE_APPLICATION_CREDENTIALS, property ID at GA4_PROPERTY_ID (507996912)GSC_SITE_URLtmp/analytics/ and can be regenerated anytimereports/gtm/YYYY-MM-DD.md, never overwritten| File | Purpose |
|------|---------|
| scripts/analytics/pull_meta_ads.py | Meta Ads data → JSON (campaigns, ads, boosted posts) |
| scripts/analytics/pull_instagram_insights.py | Instagram insights → JSON (with engagement rate) |
| scripts/analytics/pull_ga4.py | GA4 site analytics → JSON |
| scripts/analytics/pull_search_console.py | Search Console SEO data → JSON |
| scripts/analytics/generate_report.py | Assemble all JSON → markdown report |
| reports/gtm/YYYY-MM-DD.md | Unified output report |
| docs/content-strategy.md | Posting frequency rules, scaling phases, and triggers |
| tmp/analytics/*.json | Intermediate data files |
development
Best practices for Remotion - Video creation in React
tools
Fully autonomous Pinterest pin production for Clarido. Auto-selects topics from blog gaps, generates content with pre-render validation, visual-reviews rendered PNGs via agent, publishes via Chrome automation, and emails results. No approval gates. Supports batch mode.
development
Produce an Instagram Reel for Clarido — remix an existing TikTok concept with a deeper script, new voiceover, and expanded illustrations, then publish via the Instagram API. Use when creating new Instagram Reels content.
business
End-to-end ad creative generation for Clarido — from performance analysis to rendered video variants. Use when creating new ad creatives, video ads, or marketing content.