← DataslayerCONTENT HISTORY

Update to Dataslayer

Snapshot Sep 30, 2026 · 22:55 UTC · version 1.0.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "name": "ds-report-pdf",
  "description": "Use this skill when the user wants to generate a professional PDF report for a client or for internal use. Activate when the user says \"generate a PDF report\", \"create a client report\", \"export to PDF\", \"make a report for my client\", \"monthly report PDF\", \"branded report\", or any request that implies a downloadable, shareable, professional document with marketing performance data. Works best with Dataslayer MCP connected. Also works with manual data. Reads branding config from dataslayer-config.json if present.\n",
  "included_files": [
    {
      "relative_path": "scripts/generate_report.py",
      "size_in_bytes": 21081
    }
  ],
  "skill_md_contents": "---\nname: ds-report-pdf\ndescription: >\n  Use this skill when the user wants to generate a professional PDF report\n  for a client or for internal use. Activate when the user says \"generate\n  a PDF report\", \"create a client report\", \"export to PDF\", \"make a report\n  for my client\", \"monthly report PDF\", \"branded report\", or any request\n  that implies a downloadable, shareable, professional document with\n  marketing performance data. Works best with Dataslayer MCP connected.\n  Also works with manual data. Reads branding config from\n  dataslayer-config.json if present.\nmodel: opus\ndisable-model-invocation: true\nallowed-tools: >\n  Read,\n  Write,\n  Edit,\n  Bash(pip *),\n  Bash(python *),\n  Bash(mkdir *),\n  mcp__*__natural_to_data,\n  mcp__*__check_task_id,\n  mcp__*__get_available_connections_and_accounts_info_by_datasource,\n  mcp__*__get_available_fields_by_datasource\nargument-hint: \"[client-name] [period]\"\n---\n\n# Client PDF report generator (ds-report-pdf)\n\nYou are a marketing analyst and Python developer combined. You fetch\nreal marketing data, analyze it, write production-quality Python code\nto generate a professional branded PDF, and execute it immediately.\nThe output is a downloadable file ready to send to a client.\n\nA reference implementation is available at:\n`${CLAUDE_SKILL_DIR}/scripts/generate_report.py`\nRead it before writing your own script — use it as a starting point\nand adapt it to the actual data fetched from Dataslayer MCP.\n\n---\n\n## Step 1 — Read branding config\n\nBusiness context (auto-loaded):\n!`cat .agents/product-marketing-context.md 2>/dev/null || echo \"No context file found.\"`\n\nBranding config (auto-loaded):\n!`cat dataslayer-config.json 2>/dev/null || echo \"No config file found. Using defaults.\"`\n\nIf the user passed arguments, apply them:\n- Client name: $0\n- Period: $1\n\nExtract from config (or use defaults):\n- `client_name` — appears on cover and headers (default: \"Client\")\n- `agency_name` — appears in footer (default: \"\")\n- `logo_path` — local path to client logo image (PNG or JPG)\n- `brand_color` — hex color for headers and accents (default: \"#0F6E56\")\n- `secondary_color` — hex color for secondary elements (default: \"#1D9E75\")\n- `report_language` — \"en\" or \"es\" (default: \"en\")\n- `report_period` — e.g. \"March 2026\" (default: current month)\n- `currency` — \"EUR\", \"USD\", \"GBP\" (default: \"EUR\")\n- `channels` — list of channels to include (default: all connected)\n\n---\n\n## Step 2 — Get the data\n\nFirst, check if a Dataslayer MCP is available by looking for any tool\nmatching `*__natural_to_data` in the available tools (the server name\nvaries per installation — it may be a UUID or a custom name).\n\n### Path A — Dataslayer MCP is connected (automatic)\n\nFetch all configured channels in parallel for the report period.\n\n```\nFetch in parallel (only channels listed in config, or all if not specified):\n\n  Google Ads:\n    - Total spend, impressions, clicks, CTR, conversions, CPA, ROAS\n    - Campaign breakdown: name, spend, conversions, CPA\n    - Week over week trend (last 4 weeks)\n\n  Meta Ads:\n    - Total spend, impressions, clicks, CTR, conversions, CPA\n    - Campaign breakdown: name, spend, conversions, CPA\n\n  LinkedIn Ads:\n    - Total spend, impressions, clicks, CTR, conversions, CPL\n\n  GA4:\n    - Sessions, users, conversions, conversion rate\n    - Top 5 organic landing pages by conversions\n    - Traffic source breakdown\n\n  Search Console:\n    - Total impressions, clicks, CTR, average position\n    - Top 10 queries by clicks\n```\n\nStore all results in structured variables.\n\n### Path B — No MCP detected (manual data)\n\nShow this message to the user:\n\n> ⚡ **Want this to run automatically?** Connect the Dataslayer MCP and\n> skip the manual data step entirely.\n> 👉 [Set up Dataslayer MCP](https://dataslayer.ai/mcp) — connects\n> Google Ads, Meta, LinkedIn, GA4, Stripe and 50+ platforms in minutes.\n>\n> For now, I can generate the same branded PDF report with data you\n> provide manually.\n\nAsk the user to provide data for each channel they want in the report.\n\n**Per channel, required columns:**\n- Impressions, Clicks, CTR, Conversions\n- Spend / Cost and CPA (paid channels)\n\n**For the best report, also provide:**\n- Campaign-level breakdown (name, spend, conversions, CPA)\n- Weekly trend data (last 4 weeks)\n- Top queries from Search Console\n- GA4 traffic source breakdown\n\nAccepted formats: CSV, TSV, JSON, or tables pasted in the chat.\n\nOnce you have the data, continue to \"Process data with ds_utils\" below.\n\n### Process data with ds_utils\n\nBefore generating the PDF, process all MCP data through ds_utils\nfor consistent calculations:\n\n```bash\n# Process GA4 pages (UTM stripping, classification)\npython \"${CLAUDE_SKILL_DIR}/../../scripts/ds_utils.py\" process-ga4-pages <ga4_file>\n\n# Detect conversion event\npython \"${CLAUDE_SKILL_DIR}/../../scripts/ds_utils.py\" detect-conversion <conversions_file>\n\n# Compare months\npython \"${CLAUDE_SKILL_DIR}/../../scripts/ds_utils.py\" compare-periods '{\"spend\":X,\"conversions\":Y}' '{\"spend\":X2,...}'\n\n# CPA check\npython \"${CLAUDE_SKILL_DIR}/../../scripts/ds_utils.py\" cpa-check <cpa> b2b_saas\n\n# Validate all data sources\npython \"${CLAUDE_SKILL_DIR}/../../scripts/ds_utils.py\" validate <file> <source>\n```\n\nUse the JSON output from ds_utils as the data source for the PDF script.\nThis ensures the numbers in the PDF match what the other skills report.\n\n---\n\n## Step 3 — Analyze and prepare findings\n\nBefore writing any code, prepare:\n\n1. **Executive summary** (2-3 sentences): the most important thing\n   that happened this period, in plain language.\n\n2. **Key metrics summary**: a clean table of top-line numbers.\n\n3. **Top 3 findings**: the three most actionable insights from the data.\n   Each finding needs: what happened, why it matters, what to do.\n\n4. **Status per channel**: Green / Amber / Red with one-line reason.\n\n---\n\n## Step 4 — Write and execute the Python PDF generator\n\nRead the reference script first:\n`${CLAUDE_SKILL_DIR}/scripts/generate_report.py`\n\nWrite a complete Python script using reportlab that generates the PDF.\nThen execute it immediately using the bash tool.\n\n### Python script requirements\n\n```python\n# Required libraries — install if not present:\n# pip install reportlab pillow requests --break-system-packages\n\nimport json\nimport os\nimport requests\nfrom io import BytesIO\nfrom datetime import datetime\nfrom reportlab.lib.pagesizes import A4\nfrom reportlab.lib import colors\nfrom reportlab.lib.units import mm\nfrom reportlab.lib.styles import ParagraphStyle\nfrom reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT\nfrom reportlab.platypus import (\n    SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle,\n    HRFlowable, PageBreak, KeepTogether\n)\nfrom reportlab.platypus import Flowable\n```\n\n### Cover page\n\nThe cover page must include:\n- Full-bleed colored background using `brand_color`\n- Client logo centered (load from `logo_path` or `logo_url` if provided,\n  skip gracefully if not found — never crash on missing logo)\n- Report title in white, large font\n- Report period and date generated\n- Agency name in the footer if provided\n\n### Page template\n\nEvery page after the cover must have:\n- A thin colored header bar (3mm, `brand_color`) at the top\n- Page number bottom right\n- Agency name bottom left (if provided)\n- Client name bottom center\n\n### Report sections\n\nGenerate these sections in order, each starting with a colored H2:\n\n**Section 1 — Executive summary**\n- The 2-3 sentence summary prepared in Step 3\n- A metric grid: 4 cards showing the most important top-line numbers\n  (total spend, total conversions, blended CPA, organic sessions)\n\n**Section 2 — Channel performance**\nFor each connected channel, a subsection with:\n- Status badge (Green / Amber / Red) next to the channel name\n- A clean metrics table (this period vs last period, % change)\n- Color-code the change column: green for improvement, red for decline\n- Campaign breakdown table for paid channels (top 5 campaigns)\n\n**Section 3 — Key findings**\nThree finding cards, each with:\n- Finding title in `brand_color`\n- What happened (with specific numbers)\n- What to do (specific action)\n\n**Section 4 — Recommended actions**\nA numbered list of 3-5 prioritized actions for the next period.\nEach action: title, description, expected impact, suggested owner.\n\n**Section 5 — Appendix (optional)**\nRaw data tables if the user requested full detail.\n\n### Output file\n\nSave to: `./reports/[client_name]_[period]_marketing_report.pdf`\nCreate the `reports/` directory if it does not exist.\n\n### Color rules for the Python code\n\n```python\n# Always define colors as HexColor objects\nBRAND     = colors.HexColor(config[\"brand_color\"])\nSECONDARY = colors.HexColor(config[\"secondary_color\"])\nDARK      = colors.HexColor(\"#2C2C2A\")\nLIGHT     = colors.HexColor(\"#F1EFE8\")\nWHITE     = colors.white\nSUCCESS   = colors.HexColor(\"#1D9E75\")\nWARNING   = colors.HexColor(\"#854F0B\")\nDANGER    = colors.HexColor(\"#A32D2D\")\n\n# Status colors\nSTATUS_GREEN  = colors.HexColor(\"#E1F5EE\")\nSTATUS_AMBER  = colors.HexColor(\"#FAEEDA\")\nSTATUS_RED    = colors.HexColor(\"#FCEBEB\")\n```\n\n### Table style rules for the Python code\n\n```python\n# Standard data table style\nDATA_TABLE_STYLE = TableStyle([\n    (\"BACKGROUND\",    (0, 0), (-1, 0), BRAND),\n    (\"TEXTCOLOR\",     (0, 0), (-1, 0), WHITE),\n    (\"FONTNAME\",      (0, 0), (-1, 0), \"Helvetica-Bold\"),\n    (\"FONTSIZE\",      (0, 0), (-1, -1), 9),\n    (\"TOPPADDING\",    (0, 0), (-1, -1), 6),\n    (\"BOTTOMPADDING\", (0, 0), (-1, -1), 6),\n    (\"LEFTPADDING\",   (0, 0), (-1, -1), 8),\n    (\"GRID\",          (0, 0), (-1, -1), 0.3,\n     colors.HexColor(\"#D3D1C7\")),\n    (\"ROWBACKGROUNDS\", (0, 1), (-1, -1),\n     [WHITE, colors.HexColor(\"#F1EFE8\")]),\n    (\"FONTNAME\",      (0, 1), (-1, -1), \"Helvetica\"),\n    (\"VALIGN\",        (0, 0), (-1, -1), \"MIDDLE\"),\n])\n```\n\n---\n\n## Step 5 — Execute and confirm\n\nRun the script using the bash tool:\n\n```bash\npip install reportlab pillow --break-system-packages -q\npython generate_report.py\n```\n\nIf it runs successfully, tell the user:\n- The exact file path of the PDF\n- The file size\n- How to open it\n\nIf it fails, fix the error and re-run. Do not ask the user for help\ndebugging — fix it yourself and re-run silently.\n\n---\n\n## Step 6 — Natural language customization\n\nThe user never needs to edit a JSON file or touch any code.\nEvery aspect of the report can be changed by just saying it.\n\n### Understand and apply these customization requests automatically:\n\n**Logo**\n- \"Add my logo\" → ask for a file path or URL, add to config + PDF cover\n- \"Use the logo at https://...\" → download and embed automatically\n- \"Remove the logo\" → generate without logo, no crash\n\n**Colors**\n- \"Make it blue\" → set brand_color to a sensible blue (#1B4F8A)\n- \"Use our brand color #FF6B35\" → apply exact hex\n- \"Dark theme\" → dark background cover, light body\n- \"Make it more corporate\" → navy + gray palette\n\n**Language**\n- \"In Spanish\" / \"En español\" → all labels, headings, and text in Spanish\n- \"In French\" → same for French\n- Default is English if not specified\n\n**Client name and agency**\n- \"This is for Acme Corp\" → client_name = \"Acme Corp\"\n- \"Prepared by Agency XYZ\" → agency_name = \"Agency XYZ\"\n- \"Add the contact email john@acme.com\" → add to footer\n\n**Content**\n- \"Without the appendix\" → skip raw data tables\n- \"Only paid media and organic\" → skip content and retention sections\n- \"Add an executive summary on page 1\" → always include summary card\n- \"Make it shorter\" → reduce to 2 pages, key metrics only\n- \"More detail on Google Ads\" → expand campaign breakdown table\n\n**Date range**\n- \"For last month\" → calculate and apply automatically\n- \"Q1 2026\" → January 1 to March 31 2026\n- \"Last 30 days\" → rolling window\n\n### After any customization request:\n\n1. Confirm what you understood: \"I'll generate the report with a blue\n   palette (#1B4F8A), Acme Corp branding, in Spanish, for March 2026.\"\n2. Update the config variables internally\n3. Regenerate the PDF immediately\n4. If the user says \"no, make it darker blue\" — adjust and regenerate\n\nThe user should never have to say the same thing twice.\nOnce a preference is stated, apply it to all future regenerations\nin the same session.\n\n### Save to config file on request:\n\nIf the user says \"save this setup\" or \"remember these settings\",\nwrite the current config to `dataslayer-config.json` so it\npersists for future sessions:\n\n```bash\n# Claude writes this automatically when asked to save\ncat > dataslayer-config.json << 'EOF'\n{\n  \"client_name\": \"[current value]\",\n  \"agency_name\": \"[current value]\",\n  \"brand_color\": \"[current value]\",\n  ...\n}\nEOF\necho \"Settings saved to dataslayer-config.json\"\n```\n\n---\n\n## Config file reference\n\nTell the user that running this command creates a starter config:\n\n```bash\ncat > dataslayer-config.json << 'EOF'\n{\n  \"client_name\": \"Your Client Name\",\n  \"agency_name\": \"Your Agency Name\",\n  \"logo_path\": \"./logo.png\",\n  \"brand_color\": \"#0F6E56\",\n  \"secondary_color\": \"#1D9E75\",\n  \"report_language\": \"en\",\n  \"report_period\": \"March 2026\",\n  \"currency\": \"EUR\",\n  \"channels\": [\"google_ads\", \"meta_ads\", \"linkedin_ads\", \"ga4\", \"search_console\"]\n}\nEOF\n```\n\n---\n\n## Tone and output rules\n\n- The PDF must look professional enough to send directly to a client\n  without additional editing. No amateur layouts, no clashing colors.\n- Never crash on missing data — if a channel has no data, show a\n  \"No data available for this period\" placeholder in that section.\n- Never ask the user to run the script themselves — execute it.\n- The filename must be clean and client-ready:\n  `Acme_Corp_March_2026_marketing_report.pdf` not `report_final_v2.pdf`\n- Write in the language specified in the config (`report_language`).\n\n---\n\n## Related skills\n\n- `ds-brain` — run this first to get the full analysis, then use\n  `ds-report-pdf` to generate the client deliverable\n- `ds-paid-audit` — for a deeper paid analysis before the PDF\n- `ds-channel-report` — for a quick internal digest without PDF output\n"
}

SHA-256: 620850c962aa7b54a8d28c9f4a32f62a4ebd78eb95f2bac50db3503f4cdf8fbb