Docs · page 07 of 09
Knowing what worked: results, Hits and pollination
Studio can only learn from posts it can measure. This page covers how real engagement gets in, how a sighting on LinkedIn becomes a result attached to your draft, what the numbers mean, and how a post that performed becomes the seed of the next one.
Getting engagement into Studio
Before any of the extension paths work, open the extension's Options and fill in three fields: Studio URL (Send to Studio), Studio token (x-studio-token), and My LinkedIn profile URL. Without the first two every capture answers Studio not configured — set the URL + token in Options → Studio Bridge. Without the third the daily sweep answers set "My profile URL" in Settings to enable the daily harvest, and the manual harvest loses its wrong-profile guard.
Once that is done, LinkedIn engagement reaches Studio five ways, and you can use all of them.
Automatically, once a day. The extension's Options carry a toggle, Track my posts' performance daily, which is on by default. Once every 24 hours it opens your own Activity page in a background tab, scans it, sends what it saw, and closes the tab. This is the path that keeps the loop fed without you doing anything; leave it on.
Automatically, while you browse. The Options toggle Auto-harvest while browsing is off by default. With it on — and your profile URL set, which is how the extension recognises your own work — your own posts are reported as you scroll past them, even at zero engagement.
On demand, from your Activity page: open your LinkedIn profile → Activity → Posts, then click Harvest my posts (this page) in the extension popup. Your own posts go to a separate store with no minimum-score filter, so quiet posts are kept too. Every ingest triggers a targeted reconcile immediately.
To capture one post's analytics: open that post's analytics page, right-click, and choose Capture post analytics to Studio. The page toast reads ✓ Analytics saved to Studio, with — N impressions appended when the page gave a figure. The menu item only appears on https://www.linkedin.com/analytics/*; elsewhere the extension answers Right-click on a post analytics page (linkedin.com/analytics/…). If Studio cannot match the URL to a post, you get No matching Studio post for this URL yet — harvest your posts once (popup → Harvest MY posts), then retry.
To import LinkedIn's official export: this is the path that needs no extension at all. Go to LinkedIn → Analytics → Post impressions → Export, then in Studio open Settings → Traction loop, pick the file under Import LinkedIn analytics export (.xlsx / .csv) and press Import analytics file. Pick the file first or the line reads Pick your LinkedIn analytics export first (.xlsx or .csv). The result line reads ✓ N rows — N matched, N unmatched, N new snapshots. The file is parsed on your own Studio server and never leaves it. Body limit is 15MB.
To refresh Facebook and Instagram: open Hits and press Refresh counts. Studio re-reads counts through the Graph API for published Facebook and Instagram publications sent in the last 45 days, using each Page's own token, and toasts Checked N · N changed (plus · N failed when a Page's token has died). The same pass runs on its own every six hours, and once about two minutes after the server starts.
Good to know
LinkedIn has no per-publication fetch. There is no API call that hands Studio the counts for one LinkedIn publication, so Refresh counts does nothing for LinkedIn — those counts arrive only through the harvest, the right-click capture or the export import, and Hits attributes the post-level snapshot to that post's LinkedIn publication.
Meta does not give the same fields everywhere. Instagram returns likes and comments only, so an Instagram publication's share count is always 0. A Facebook Page post returns reactions, comments and shares; a Facebook photo or video object does not, and Studio falls back to likes and comments for it.
The import needs a real header row: a Post URL or link column plus at least one of Impressions / Likes / Reactions / Comments / Shares / Reposts, inside the first 10 rows. Otherwise you get
no per-post rows found (need a header row with a Post URL/link column plus Impressions/Likes/Comments/Reposts). A file that is not a readable workbook answerscould not parse file: …, and sending neither field answersprovide xlsxBase64 (LinkedIn analytics export) or csvText.
How a sighting becomes a result
The reconciler joins what the extension saw to what Studio published. It tries an exact URN or permalink match first, against both posts.permalink and posts.external_id — a post published through the API carries a share URN while the feed shows an activity URN, and the two never collide, so the URN match is the trustworthy one.
When that finds nothing, it falls back to a content key: the post body lowercased, stripped to letters and digits, first 160 characters. The key is always scoped to one workspace, it is refused below 40 characters, and if two posts in that workspace share the same key the match is skipped rather than guessed. It scans the 1,000 most recent posts that are published or manual — manual rows are in the scan on purpose, because that is what makes the next paragraph possible.
Every linked sighting appends an engagement snapshot. Identical counts seen again within six hours are suppressed, so the series records change, not polling. A post you published by hand (status manual) that the reconciler confirms is flipped to published, and a line is written to its publish log.
To run it now: Settings → Traction loop → Reconcile + recompute now. It also runs after every self-post ingest and once a day per workspace from the scheduler.
Reading one post: the Results scorecard
Open a published post's edit modal and the 📊 Results panel appears — on a draft or a scheduled post it stays hidden. Each row only shows when there is something to put in it:
- Engagement — the latest snapshot: likes, comments, reposts, and impressions when any source supplied them.
- Score — the engagement score, with the snapshot count when there is more than one.
- Cost to create — model spend plus media spend for that post, and dollars per engagement. A post written on the free path with no recorded spend has no cost row at all. (Dollars per like is computed by the API but not shown here.)
- Judge predicted — the winning draft's weighted judge total out of 10. Shown only for a post that carries a stored judge verdict.
- Publish events — how many attempts the publish log holds.
With no snapshots yet, the Engagement row reads: No snapshots yet — browse your post with the extension on, or import your analytics export in Settings → Traction loop. The series is capped at 200 snapshots and the log at 50 events.
What the loop feeds back into generation
Mining runs deterministically, with no model call. Over your last 180 days and at most 50 measured published posts, Studio computes the median engagement score, then each post's outcome index against it, and derives:
- the top three and bottom three hooks by outcome index, as angles to lean toward and angles to avoid;
- empirical best windows — day-and-hour buckets with at least two posts each, best average first, top three, in the Asia/Singapore audience timezone;
- the best length bucket among
<120,120-220and>220words, again needing at least two posts per bucket.
None of it reaches a prompt until five posts have been reconciled with metrics. Below that the block is empty. The assembled block is capped at 2,000 characters and sliced to 2,400 where generation injects it. The Traction loop card in Settings shows the state: the pill moves from No data yet to N posts measured, and the summary reads either Feeds generation once 5 posts are measured. or Feeding generation with measured hooks + windows.
Judge-weight recalibration
Studio also checks whether its own judge was right. For each of the seven rubric dimensions it computes a Pearson correlation between the winning draft's score on that dimension and the post's realized outcome index.
This is gated at eight judged posts with outcomes. Each correlation is clamped to ±0.5 so a small noisy sample cannot swing a weight, every dimension keeps a floor of 0.03 so none is ever zeroed out, and the result is renormalized to sum to 1. It blends into the shipped rubric — it never replaces it. Posts judged by the pre-2026-09-06 rubric are excluded rather than counted as zeros. When it has run, the Settings card adds Judge weights recalibrated from your outcomes.
Hits: ranked against your own brand
The Hits view lists your published publications over a 14 days / 30 days / 90 days window. Ranking is relative: each publication is scored against the median of its own (brand, platform) group over that window, so a card reads top 12% for this brand · 2.4× its median. A group with fewer than three publications has no fair median; those keep their absolute score and are labelled one of 2 on this brand — too few to rank, and they sort last. That is the whole point — a small Page's best post should be able to outrank a big Page's average one.
Cards in the top quartile are highlighted. With nothing measured yet you see N publications in the window, none with counts yet — press Refresh counts., or Nothing published in this window yet. A hint line reports how many publications still have no counts. The list shows the top 50.
Pollinate: carrying an idea to another brand
To pollinate a hit: press Pollinate → on its card, tick the brands the idea should travel to, then press Create drafts. Studio creates one derived draft per brand, with that brand's own accounts as the destinations, records derived_from lineage back to the publication that earned it, and queues a rewrite for each brand on the free path. The card then reads 2 drafts created · rewrite queued. — or 2 drafts created. when the queue write failed and you will have to edit them by hand — and a toast names the brands. An Open in Compose button appears next to it for the first derived draft.
Pollinate never publishes anything. It only creates drafts.
The sheet offers the other brands that have at least one connected account. The brand the hit came from is never offered, and if you pass it anyway it is skipped with that is the brand it came from; a brand with no connected account is not offered either. If no brand qualifies, the Pollinate → button does not appear on that card at all — connect an account to a second brand first.
Ticking nothing answers Tick the brands this idea should travel to. Other refusals: pick at least one brand, publication not found, and this publication has no text to carry.
Auto-seed
To let a brand's hits seed your others unattended: open Settings → Brands, find the brand, and tick Let hits from this brand seed my other brands — one draft per brand, never published by itself. Set the threshold (top 10% / top 25% / top 50%, default top 25%) and the window (last 14 / 30 / 90 days, default 30) — then press that brand row's Save button. Nothing is stored until you do; the row confirms with Saved.
It is off by default, and it only ever produces drafts. A publication that is too unranked to be judged never seeds. A hit seeds a given brand once, ever. At most four pairs are seeded per workspace per run, and the run happens every six hours, right after the Meta counts refresh.
On credits: Pollinate and auto-seed queue their rewrites on the free path and spend nothing. Credits bound the on-demand ↻ Rewrite for this brand button in Compose for workspaces that run on Studio's key — one credit per rewrite, atomically taken, refunded when the model call fails or returns nothing. Out of credits, that button answers HTTP 402 with no credits left (balance 0).
Reading the numbers honestly
The engagement score is the same everywhere in Studio: like ×1 + comment ×10 + repost ×20. A comment is worth ten likes and a repost twenty because that is roughly what they signal.
Check the unmeasured count on the Hits page before you draw a conclusion. Publications without counts are not zeros — they are simply not measured, and they are excluded from the ranking rather than dragging the median down.
Finally: comparisons within one author hold, comparisons across authors do not. Studio's own trait work is explicit about this — in the harvested feed, 53% of posts come from single-post authors, where "engagement" is mostly follower count, and a within-author hold-out over the 16 authors with four or more posts reversed sign on every feature. Your own posts across eras are a real signal; someone else's like count next to yours is not.
For whoever runs this Studio — never test against the live free-gen queue
This one is not a setting in the app; it is a rule about the server. The free-gen queue is production, drained by cron jobs on the host with real workers attached, so a fixture queued "just to test" can be claimed, generated, and land on the Content Calendar as a real post. That has happened. If you must exercise the queue, stop the drain cron entries first, mark the fixtures unmistakably, and check for leftover posts — not just leftover queue items — before you call it done.