Buffer Analytics: SQLite Ingestion & SQL Query Engine
The buffer-analytics skill provides high-performance data warehousing and SQL querying for social media data downloaded via the Buffer CLI (@bufferapp/cli). It ingests raw payloads without filtering into a local SQLite database and provides a SQL interface for deep content crunching.
Available scripts
scripts/buffer_analytics.py: Automated sync and report CLI (incremental sync, backfill, pre-packaged reports, ad-hoc queries). Executed via uv run scripts/buffer_analytics.py (requires Node.js 18+ and @bufferapp/cli).
scripts/test_buffer_analytics.py: Unit and regression test suite validating schema, query extraction, and CLI flags.
⚡ Quick Start & Primary Actions
All operations are driven via the bundled Python script in scripts/buffer_analytics.py:
# 1. Incremental Sync (New posts + 2-day lookback metrics refresh)
uv run scripts/buffer_analytics.py sync --db path/to/database.db
# 2. Full Historical Backfill (Paginates through entire history)
uv run scripts/buffer_analytics.py sync --full --db path/to/database.db
# 3. Run Pre-Packaged Reports
uv run scripts/buffer_analytics.py report overview --db path/to/database.db
uv run scripts/buffer_analytics.py report top-posts --db path/to/database.db
uv run scripts/buffer_analytics.py report channels --db path/to/database.db
uv run scripts/buffer_analytics.py report timing --db path/to/database.db
uv run scripts/buffer_analytics.py report hooks --db path/to/database.db
# 4. Run Ad-Hoc SQL Query
uv run scripts/buffer_analytics.py query "SELECT service, AVG(impressions), AVG(reactions) FROM v_posts_summary WHERE status = 'sent' GROUP BY service" --db path/to/database.db
If --db is omitted, the script defaults to buffer_analytics.db in the current working directory.
🗄️ Database Schema & Relational Structure
The database maintains 6 normalized relational tables and high-performance SQL views. Detailed DDL and schema definitions are in references/schema.md.
Tables
channels: Connected social accounts and metadata.
- Key columns:
id (PK), organization_id, name, service (linkedin, twitter, bluesky), display_name, timezone, is_disconnected, raw_json, synced_at.
posts: Individual posts, scheduling state, and content.
- Key columns:
id (PK), channel_id (FK), channel_service, status (sent, scheduled, draft), text, external_link, sent_at, due_at, char_count, word_count, has_link, has_media, thread_count, raw_json, synced_at.
post_metrics: Time-series metrics per post.
- Key columns:
id (PK), post_id (FK), channel_service, metric_type (impressions, reach, reactions, comments, reposts, clicks, engagementRate), value, synced_at.
post_assets: Attached images, videos, and media URLs.
- Key columns:
id (PK), post_id (FK), type, mime_type, source, thumbnail, raw_json.
post_tags: Campaign and topic tags assigned in Buffer.
- Key columns:
id, post_id (FK), name, color.
sync_history: Audit trail of all sync executions.
- Key columns:
id (PK), channel_id, sync_mode, posts_fetched, posts_inserted, posts_updated, started_at, status.
📊 Core Analytical View: v_posts_summary
The primary view for SQL analytics is v_posts_summary, which pivots metrics and computes calendar dimensions:
| Column |
Type |
Description |
post_id |
TEXT |
Buffer Post ID |
service |
TEXT |
Network (linkedin, twitter, bluesky) |
channel_name |
TEXT |
Account handle/name |
status |
TEXT |
sent, scheduled, draft |
sent_at |
TEXT |
Full ISO timestamp |
sent_date |
TEXT |
Publication date (YYYY-MM-DD) |
year_month |
TEXT |
Calendar month (YYYY-MM) |
day_of_week |
TEXT |
Day name (Monday, Tuesday, etc.) |
hour_of_day |
INTEGER |
UTC hour (0–23) |
char_count / word_count |
INTEGER |
Text length metrics |
has_link / has_media |
INTEGER |
1 if link or media is present |
thread_count |
INTEGER |
Number of posts in thread |
impressions |
REAL |
Total impressions / views |
reach |
REAL |
Unique accounts reached |
reactions |
REAL |
Likes and reactions |
comments |
REAL |
Comments received |
reposts |
REAL |
Retweets / reshares |
clicks |
REAL |
Link click count |
engagement_rate |
REAL |
Total engagement % |
external_link |
TEXT |
Live post URL |
text |
TEXT |
Full text copy |
🔍 SQL Analytics Cookbook
Pre-tested SQL query recipes are documented in references/queries.md.
1. Best Day of the Week by Channel
SELECT
service,
day_of_week,
COUNT(*) AS posts,
ROUND(AVG(impressions), 0) AS avg_impressions,
ROUND(AVG(reactions), 1) AS avg_reactions,
ROUND(AVG(engagement_rate), 2) AS avg_eng_rate
FROM v_posts_summary
WHERE status = 'sent' AND day_of_week IS NOT NULL
GROUP BY service, day_of_week
ORDER BY service, avg_impressions DESC;
2. Best Posting Hours (UTC)
SELECT
service,
hour_of_day || ':00 UTC' AS hour,
COUNT(*) AS posts,
ROUND(AVG(impressions), 0) AS avg_impressions,
ROUND(AVG(reactions), 1) AS avg_reactions
FROM v_posts_summary
WHERE status = 'sent' AND impressions > 0
GROUP BY service, hour_of_day
HAVING COUNT(*) >= 3
ORDER BY avg_impressions DESC;
3. Impact of Links in Body vs. First Comment
SELECT
service,
CASE WHEN has_link = 1 THEN 'Link in Body' ELSE 'No Link / First Comment' END AS placement,
COUNT(*) AS posts,
ROUND(AVG(impressions), 0) AS avg_impressions,
ROUND(AVG(reactions), 1) AS avg_reactions
FROM v_posts_summary
WHERE status = 'sent' AND service = 'linkedin'
GROUP BY placement;
📚 Progressive Disclosure & References
- Full DDL Schema Reference:
references/schema.md — Exact SQL table definitions, column types, constraints, and views.
- SQL Query Recipes:
references/queries.md — Analytical queries for timing, link penalties, hooks, and topic cohorts.
- Workflows Guide:
references/workflows.md — Operational guidance for periodic backfills and cron automations.
- Inquiry Playbook:
references/inquiry_playbook.md — Strategic questions for campaign and social retrospectives.
1---2name: buffer-analytics3description: Collect and analyze social media data from Buffer in a local SQLite database. Stores your full post history and metrics across connected channels (such as LinkedIn, X/Twitter, Bluesky, and others) so you can run SQL queries or view reports on engagement, clicks, and views. Activate when you need to analyze social media performance, find the best days or times to post, identify top-performing content, or query Buffer data with SQL.4license: Apache-2.05---67# Buffer Analytics: SQLite Ingestion & SQL Query Engine89The `buffer-analytics` skill provides high-performance data warehousing and SQL querying for social media data downloaded via the Buffer CLI (`@bufferapp/cli`). It ingests raw payloads without filtering into a local SQLite database and provides a SQL interface for deep content crunching.1011## Available scripts12- `scripts/buffer_analytics.py`: Automated sync and report CLI (incremental sync, backfill, pre-packaged reports, ad-hoc queries). Executed via `uv run scripts/buffer_analytics.py` (requires Node.js 18+ and `@bufferapp/cli`).13- `scripts/test_buffer_analytics.py`: Unit and regression test suite validating schema, query extraction, and CLI flags.1415---1617## ⚡ Quick Start & Primary Actions1819All operations are driven via the bundled Python script in `scripts/buffer_analytics.py`:2021```bash22# 1. Incremental Sync (New posts + 2-day lookback metrics refresh)23uv run scripts/buffer_analytics.py sync --db path/to/database.db2425# 2. Full Historical Backfill (Paginates through entire history)26uv run scripts/buffer_analytics.py sync --full --db path/to/database.db2728# 3. Run Pre-Packaged Reports29uv run scripts/buffer_analytics.py report overview --db path/to/database.db30uv run scripts/buffer_analytics.py report top-posts --db path/to/database.db31uv run scripts/buffer_analytics.py report channels --db path/to/database.db32uv run scripts/buffer_analytics.py report timing --db path/to/database.db33uv run scripts/buffer_analytics.py report hooks --db path/to/database.db3435# 4. Run Ad-Hoc SQL Query36uv run scripts/buffer_analytics.py query "SELECT service, AVG(impressions), AVG(reactions) FROM v_posts_summary WHERE status = 'sent' GROUP BY service" --db path/to/database.db37```3839If `--db` is omitted, the script defaults to `buffer_analytics.db` in the current working directory.4041---4243## 🗄️ Database Schema & Relational Structure4445The database maintains 6 normalized relational tables and high-performance SQL views. Detailed DDL and schema definitions are in [`references/schema.md`](references/schema.md).4647### Tables48491. **`channels`**: Connected social accounts and metadata.50 - Key columns: `id` (PK), `organization_id`, `name`, `service` (`linkedin`, `twitter`, `bluesky`), `display_name`, `timezone`, `is_disconnected`, `raw_json`, `synced_at`.512. **`posts`**: Individual posts, scheduling state, and content.52 - Key columns: `id` (PK), `channel_id` (FK), `channel_service`, `status` (`sent`, `scheduled`, `draft`), `text`, `external_link`, `sent_at`, `due_at`, `char_count`, `word_count`, `has_link`, `has_media`, `thread_count`, `raw_json`, `synced_at`.533. **`post_metrics`**: Time-series metrics per post.54 - Key columns: `id` (PK), `post_id` (FK), `channel_service`, `metric_type` (`impressions`, `reach`, `reactions`, `comments`, `reposts`, `clicks`, `engagementRate`), `value`, `synced_at`.554. **`post_assets`**: Attached images, videos, and media URLs.56 - Key columns: `id` (PK), `post_id` (FK), `type`, `mime_type`, `source`, `thumbnail`, `raw_json`.575. **`post_tags`**: Campaign and topic tags assigned in Buffer.58 - Key columns: `id`, `post_id` (FK), `name`, `color`.596. **`sync_history`**: Audit trail of all sync executions.60 - Key columns: `id` (PK), `channel_id`, `sync_mode`, `posts_fetched`, `posts_inserted`, `posts_updated`, `started_at`, `status`.6162---6364## 📊 Core Analytical View: `v_posts_summary`6566The primary view for SQL analytics is `v_posts_summary`, which pivots metrics and computes calendar dimensions:6768| Column | Type | Description |69| :--- | :--- | :--- |70| `post_id` | `TEXT` | Buffer Post ID |71| `service` | `TEXT` | Network (`linkedin`, `twitter`, `bluesky`) |72| `channel_name` | `TEXT` | Account handle/name |73| `status` | `TEXT` | `sent`, `scheduled`, `draft` |74| `sent_at` | `TEXT` | Full ISO timestamp |75| `sent_date` | `TEXT` | Publication date (`YYYY-MM-DD`) |76| `year_month` | `TEXT` | Calendar month (`YYYY-MM`) |77| `day_of_week` | `TEXT` | Day name (`Monday`, `Tuesday`, etc.) |78| `hour_of_day` | `INTEGER` | UTC hour (0–23) |79| `char_count` / `word_count` | `INTEGER` | Text length metrics |80| `has_link` / `has_media` | `INTEGER` | 1 if link or media is present |81| `thread_count` | `INTEGER` | Number of posts in thread |82| `impressions` | `REAL` | Total impressions / views |83| `reach` | `REAL` | Unique accounts reached |84| `reactions` | `REAL` | Likes and reactions |85| `comments` | `REAL` | Comments received |86| `reposts` | `REAL` | Retweets / reshares |87| `clicks` | `REAL` | Link click count |88| `engagement_rate` | `REAL` | Total engagement % |89| `external_link` | `TEXT` | Live post URL |90| `text` | `TEXT` | Full text copy |9192---9394## 🔍 SQL Analytics Cookbook9596Pre-tested SQL query recipes are documented in [`references/queries.md`](references/queries.md).9798### 1. Best Day of the Week by Channel99```sql100SELECT101 service,102 day_of_week,103 COUNT(*) AS posts,104 ROUND(AVG(impressions), 0) AS avg_impressions,105 ROUND(AVG(reactions), 1) AS avg_reactions,106 ROUND(AVG(engagement_rate), 2) AS avg_eng_rate107FROM v_posts_summary108WHERE status = 'sent' AND day_of_week IS NOT NULL109GROUP BY service, day_of_week110ORDER BY service, avg_impressions DESC;111```112113### 2. Best Posting Hours (UTC)114```sql115SELECT116 service,117 hour_of_day || ':00 UTC' AS hour,118 COUNT(*) AS posts,119 ROUND(AVG(impressions), 0) AS avg_impressions,120 ROUND(AVG(reactions), 1) AS avg_reactions121FROM v_posts_summary122WHERE status = 'sent' AND impressions > 0123GROUP BY service, hour_of_day124HAVING COUNT(*) >= 3125ORDER BY avg_impressions DESC;126```127128### 3. Impact of Links in Body vs. First Comment129```sql130SELECT131 service,132 CASE WHEN has_link = 1 THEN 'Link in Body' ELSE 'No Link / First Comment' END AS placement,133 COUNT(*) AS posts,134 ROUND(AVG(impressions), 0) AS avg_impressions,135 ROUND(AVG(reactions), 1) AS avg_reactions136FROM v_posts_summary137WHERE status = 'sent' AND service = 'linkedin'138GROUP BY placement;139```140141---142143## 📚 Progressive Disclosure & References144145- **Full DDL Schema Reference**: [`references/schema.md`](references/schema.md) — Exact SQL table definitions, column types, constraints, and views.146- **SQL Query Recipes**: [`references/queries.md`](references/queries.md) — Analytical queries for timing, link penalties, hooks, and topic cohorts.147- **Workflows Guide**: [`references/workflows.md`](references/workflows.md) — Operational guidance for periodic backfills and cron automations.148- **Inquiry Playbook**: [`references/inquiry_playbook.md`](references/inquiry_playbook.md) — Strategic questions for campaign and social retrospectives.