# LinkedIn Analytics Data This directory contains imported analytics data from LinkedIn CSV exports. ## How to Import 1. Go to [LinkedIn Creator Analytics](https://www.linkedin.com/analytics/creator/content/) 2. Click **Export** to download a CSV of your content analytics 3. Save the CSV file to `exports/` directory 4. Run `/linkedin:import` in Claude Code ### Optional: add per-post saves (manual) LinkedIn's CSV export does **not** include saves, and there is no self-serve API to pull them — but the per-post save **count** is visible in your native post analytics (since ~Sept 2025). To track it, add a `Saves` column to the CSV and type the count you read off LinkedIn. The importer picks it up automatically when the column is present: ``` "Content","Date","Impressions","Reactions","Comments","Shares","Clicks","Saves" "My post...",2026-02-10,5000,100,30,15,200,42 ``` A missing column — or a blank `Saves` cell — leaves saves **unknown** (never counted as 0), and saves is **not** folded into the engagement rate (which stays comparable to older imports). Saves is the strongest organic engagement signal, so the reports surface it as its own line. **Dwell time stays unmeasurable** — it is internal to LinkedIn for organic posts, with no count to transcribe. ### Optional: add the out-of-network reach share (manual) LinkedIn splits a post's impressions into **in-network** (people who already follow or are connected to you) and **out-of-network** (people who found it through recommendations, reshares or search). It sits in your post analytics under **Discovery**, beneath the impressions count — a global rollout that began in June 2026 — and it is shown as **percentages**, not as two counts. It is **not** in the CSV export, and whether it will ever be exported is unverified. To track it, add an `Out-of-network` column and type the percentage you read off that panel. The `%` sign is optional: ``` "Content","Date","Impressions","Reactions","Comments","Shares","Clicks","Out-of-network" "My post...",2026-03-10,5000,100,30,15,200,37% ``` Details worth knowing: - **Either half works.** An `In-network` column is accepted instead and stored as its complement (`In-network 63%` → out-of-network 37). Only the out-of-network share is kept, because the two halves describe one split — storing both would let a record contradict itself. - **Both halves are cross-checked.** If you transcribe both and they do not sum to ~100 (one point of rounding slack allowed), the reading is discarded as **unknown** rather than guessing which cell was misread. - **Percent, not a count.** A value above 100 is refused (`unknown`): in one column an absolute impression count and a share are indistinguishable, so the importer will not guess. A comma is read as a decimal mark (`36,5` → 36.5%). - **Unknown is never 0.** A missing column, a blank cell, or a non-numeric cell leaves the share unknown. A genuine `0` is kept — nothing left your network. - **Not part of the engagement rate.** Reach is a distribution signal, not engagement: a high out-of-network share means the post **acquired new audience**, while high in-network engagement means it **deepened the audience you already have**. Roll-ups are impressions-weighted, so a small post with a high share cannot outvote a large one. ## Directory Structure ``` analytics/ ├── exports/ # Place LinkedIn CSV exports here ├── posts/ # Auto-generated: imported post data (JSON) ├── weekly-reports/ # Auto-generated: weekly performance reports (JSON) └── README.md # This file ``` ## Data Format ### Post Analytics (posts/*.json) Each file contains a batch of imported posts: ```json { "batchId": "batch-...", "importedAt": "2026-01-29T...", "exportFilename": "content-analytics.csv", "dateRange": { "from": "2026-01-13", "to": "2026-01-28" }, "postCount": 8, "posts": [ { "id": "abc123", "title": "First 100 chars of post...", "publishedDate": "2026-01-28", "metrics": { "impressions": 4523, "reactions": 87, "comments": 23, "shares": 12, "clicks": 156, "engagementRate": 6.15 } } ] } ``` `metrics.saves` is **optional** — present only on posts where you supplied a `Saves` column value (see "Optional: add per-post saves" above). Posts without it omit the field entirely, so older imports round-trip unchanged. ### Weekly Reports (weekly-reports/*.json) Generated via `/linkedin:report`. Contains: - Summary metrics (totals, averages) - Top and underperforming posts - Week-over-week trends - Performance alerts (spikes, drops) ## CLI Usage The analytics CLI can also be invoked directly: ```bash # Import a CSV export ANALYTICS_ROOT=./assets/analytics node --import tsx scripts/analytics/src/cli.ts import # Generate weekly report ANALYTICS_ROOT=./assets/analytics node --import tsx scripts/analytics/src/cli.ts report --week 2026-W05 # Analyze trends ANALYTICS_ROOT=./assets/analytics node --import tsx scripts/analytics/src/cli.ts trends --period month --metric impressions ``` ## Privacy All data in this directory (except this README) is gitignored. Your analytics data stays local.