Why do my LinkedIn campaign stats show different numbers?

What this page is for

If you opened a LinkedIn campaign on WarmySender between roughly May 1 and May 7, 2026, and the campaign card on the dashboard showed an "Invited" or "Connected" or "Messaged" count that didn't match what you saw on the prospect list inside the same campaign, this page is for you. Short version: every LinkedIn invite, accept, message, and reply was correctly recorded in our system, but the dashboard tile was reading from one place while the prospect list was reading from another — and one of those two places had stopped being updated. We fixed this on May 7, 2026 by making both reads come from the same source. Your numbers are accurate now.

WarmySender is a 4-pillar outreach platform — Cold Emailing, Email Warmup, LinkedIn Outreach, and Multichannel sequences. This page is part of the LinkedIn Outreach pillar and applies to LinkedIn-only campaigns (the LinkedIn side of multichannel sequences was unaffected by this issue).

What you saw on the dashboard

The contradiction looked like this on a LinkedIn campaign card:

The number on the dashboard tile was lower (or sometimes different) than the count you could see on the prospect list. Your prospects had really received the invites and messages — the activity on LinkedIn itself was correct, the prospect-level records were correct, only the rollup tile on the dashboard card was stale. The most affected campaign on the platform was off by 390 invites at the time of fix.

What was happening behind the scenes

WarmySender keeps two sets of LinkedIn campaign counters. One set lives on each prospect (their per-prospect record holds invited-at, accepted-at, messaged-at, and replied-at timestamps, plus a stream of activity events). The other set is a per-campaign rollup — a single row per campaign that adds up the per-prospect data into "total invited" / "total connected" / "total messaged" / "total replied" so the dashboard tile can render in a single fast query without summing up thousands of prospects every time you load the page.

The way these counters get updated is that the live writer increments the rollup at the moment a LinkedIn action happens — when an invite goes out, the writer bumps "total invited" by 1, and so on. Most of the time this works perfectly. But if a worker process crashed mid-write, or a database transaction had to roll back due to a concurrency conflict, an increment could occasionally drop. Over time on busy campaigns this could compound: 100 successful invites might end up bumping the counter only 95 times, and the dashboard would slowly fall behind reality.

Our other dashboard counters (the unified-table side, used for email and multichannel campaigns) already had a periodic safety-net refresher that scanned the source-of-truth records every 10 minutes and corrected any drift. But that refresher didn't know about the LinkedIn-only legacy table where most of our LinkedIn campaigns store their rollups. So the LinkedIn rollup was still vulnerable to the dropped-increment problem, while the email rollups had been protected for weeks.

What we fixed on May 7, 2026

We extended the periodic safety-net refresher to also scan the LinkedIn rollup table at the end of every 10-minute tick. The refresher recalculates each campaign's "total invited / connected / messaged / replied / inmails sent" from the source-of-truth — the per-prospect records and the activity event log — and writes them back to the rollup row if there's any drift. The math is the same one the prospect list and the activity log already use. Going forward, the rollup tile and the prospect list will always agree, even if a future writer-side increment drops.

For the four monotonic counters (invited, connected, messaged, replied), the refresher takes the larger of the stored value and the recomputed value — so it can heal up if drift exists, but it can't accidentally heal down due to a transient writer-side advance that hasn't yet shown up in the activity log. For the InMail counter, the refresher does a direct rewrite because that counter has a separate exclusion rule (we filter out a small cohort of phantom InMail records that were retroactively annotated on May 2 — see the linked InMail explainer below).

To make sure this can never silently come back, we shipped two complementary safeguards alongside the fix:

We also ran a one-shot heal pass at deploy time so 11 campaigns whose rollups were drifted at the moment of the fix were corrected immediately rather than waiting 10 minutes.

How to verify your numbers are correct today

Three easy checks, in order of confidence:

  1. Hard-refresh the dashboard. The campaign cards cache the rendered counters for 60 seconds. Hard-refresh once (Cmd-Shift-R on Mac, Ctrl-Shift-R on Windows) so you're seeing the post-fix value.
  2. Open the campaign and check the prospect list. Each prospect row shows the action timestamps directly: when the invite went out, when (or whether) it was accepted, when each follow-up was sent, and when (or whether) the prospect replied. Filter by "Invited" status to confirm the invited count, and so on. This is the ground-truth view against which the dashboard tile is now reconciled.
  3. Cross-check against the LinkedIn account itself. Open LinkedIn and the connected account that ran the campaign. The "Sent invitations" page on LinkedIn (My Network → Manage → Sent) shows every invitation that account sent. The count there should match the dashboard tile and the prospect list — three numbers, all in agreement.

If the three numbers all agree, the fix is working as intended for your campaign. If they disagree by more than 5 — wait 10 minutes for the next refresh cycle, hard-refresh once more, and re-check. If they still disagree, contact support at hello@warmysender.com with the campaign name and a screenshot of the current counter, and we'll cross-check the underlying records for your specific campaign.

Common questions

Did I lose any invites, accepts, messages, or replies? Do I need to re-run my campaign?

No, on both counts. The bug was a display issue on the dashboard rollup tile, not an activity issue. Every invite that LinkedIn shows your account having sent is real and was correctly recorded. Every accept that arrived was correctly recorded against the right prospect. Every message and reply was correctly logged. The bug only affected the per-campaign rollup that the dashboard tile reads — the underlying per-prospect data and the activity event log have always been correct. Your campaign workflow continued to act on the correct underlying data the entire time, even when the dashboard tile was stale. You don't need to re-import, re-launch, or re-enroll anything.

Will this affect my LinkedIn account safety, daily caps, or warmup ramp?

No. The fix is database-only — zero new LinkedIn API calls, zero changes to your daily invite limits, your weekly invite cap, your messaging cooldowns, your warmup ramp, or any other safety control. Your LinkedIn account's sending pace is exactly where it was before the fix. The 4-week ramp-up on new connected accounts is unchanged. Per-account daily caps and per-day weekly invite limits are unchanged. The fix only changes how we count what's already happened on the dashboard rollup — it doesn't change anything about what your account does next or how fast.

Why does the dashboard tile sometimes update later than the prospect list?

Two reasons. First, the dashboard tile recalculates on a 10-minute cycle (so newly sent activity may take up to 10 minutes to appear in the rollup, even though the prospect list updates in real time). Second, the rendered card is cached for 60 seconds in your browser, so a hard-refresh is sometimes needed to see the latest 10-minute recalculation. If you've waited more than 10 minutes and hard-refreshed, the two views should be in agreement; if they're not, that's a signal worth reporting to support.

How do I know this won't happen again?

Two layers of protection. The first is an automatic regression test in our build pipeline that seeds the exact dual-table drift scenario and asserts the safety-net refresher heals it. Any future code change that would re-introduce the bug fails the test before it can ship to production. The second is a continuous drift detector — a background job that scans every LinkedIn rollup row every hour and flags any row whose stored counter is more than 5 below the canonical count. If even one campaign trips the threshold, our internal monitoring fires an alert. The detector never modifies your campaigns; it just watches for the symptom. So the fix is protected at both the build-time and runtime layers.

Did the email side of my multichannel campaign have the same problem?

No. The email side and the unified-table LinkedIn side were already protected by an earlier safety-net fix (May 7, 2026 — the email-counter explainer linked below). The fix shipped today extends that same protection to the LEGACY LinkedIn rollup table, which is where most LinkedIn-only campaigns (not multichannel) store their stats. If your campaign is a multichannel sequence, the email-side counters were already correct; this fix brings the LinkedIn-only legacy storage to the same protection level. Going forward, every counter on every campaign type — email, LinkedIn-only, or multichannel — is healed by the same hourly drift detector and per-tick refresher.

Account safety

Zero new LinkedIn API calls or rate-limit risk. Every part of the May 7 fix runs against our database — recomputing the rollup tile from the per-prospect records and the activity event log. We don't re-run any LinkedIn actions, don't re-resolve any profiles, don't bump any daily-cap budgets, and don't touch your warmup ramp. The continuous drift detector is also read-only: it scans the database, writes an internal alert row if it finds drift, and never touches your campaigns or your accounts. Your LinkedIn account's safety profile, daily caps, weekly limits, ramp-up schedule, and per-account cooldowns are all preserved exactly as you configured them.

For the legacy LinkedIn rollup table, the recompute uses the GREATEST-of-stored-and-computed pattern for monotonic counters (invited, connected, messaged, replied) — meaning the refresher can heal UP if drift exists, but it cannot accidentally heal DOWN due to a transient writer-side advance. The InMail counter uses a direct rewrite because of a separate phantom-row exclusion (different shape, see the linked InMail explainer). Either way, the math is conservative and never produces a number worse than what the underlying records show.

Still seeing something off? Email hello@warmysender.com with your campaign name and a screenshot — we'll dig into the specific account and confirm the numbers.