Add "what changed this month" to Follower Study, ahead of the cumulative picture
Feedback: showing "102 followers to date" as the headline of a monthly report answers the wrong question — a reader wants to know what happened in the month the report covers, with the cumulative numbers as supporting context, not the other way around. Audience Composition already did this correctly (month-scoped "22 new followers" by design); Follower Study now leads the same way: which new Notable Contacts joined this specific month, and which Account Clusters grew, computed live for whatever month is selected. The existing cumulative "bimodal seniority"/"shallow-network" findings stay, just demoted to a clearly-labeled "full picture, to date" section beneath. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d4fff48384
commit
5e20823947
1 file changed
+52
-12
@@ -3974,12 +3974,19 @@ _SENIOR_TIERS = ("C-Level/Founder", "Director/Head/Principal", "Senior IC/Lead")
|
||||
_JUNIOR_TIERS = ("Student/Trainee",)
|
||||
|
||||
|
||||
def _follower_study_findings(whole, non_team, period_label):
|
||||
"""Two dynamically-computed findings in the same spirit as assets/follower_study.html's
|
||||
own hand-written ones ("bimodal seniority," "shallow-network audience") — but
|
||||
computed live from whatever's in the Directory through the selected month, not
|
||||
hardcoded to July's specific numbers, so the finding stays honest for any month
|
||||
instead of silently describing a snapshot that's since moved on."""
|
||||
def _follower_study_findings(whole, non_team, period_label, month_rows=None, clusters=None):
|
||||
"""Two dynamically-computed cumulative findings in the same spirit as
|
||||
assets/follower_study.html's own hand-written ones ("bimodal seniority,"
|
||||
"shallow-network audience") — but computed live from whatever's in the
|
||||
Directory through the selected month, not hardcoded to July's specific
|
||||
numbers, so the finding stays honest for any month instead of silently
|
||||
describing a snapshot that's since moved on.
|
||||
|
||||
Plus, ahead of those two, what actually happened THIS month specifically —
|
||||
a monthly report showing "112 followers to date" as its headline is
|
||||
answering the wrong question; the reader wants to know what changed in the
|
||||
period this report covers, with the cumulative picture as supporting
|
||||
context, not the other way around."""
|
||||
total = whole["total"]
|
||||
if not total:
|
||||
return html.Div()
|
||||
@@ -3987,8 +3994,31 @@ def _follower_study_findings(whole, non_team, period_label):
|
||||
junior_n = sum(whole["seniority"].get(t, 0) for t in _JUNIOR_TIERS)
|
||||
first_degree_n = sum(1 for d in non_team if d.get("connection") == "1st")
|
||||
|
||||
bullets = [
|
||||
f"{senior_n} of {total} ({senior_n / total * 100:.0f}%) sit at C-Level/Founder, "
|
||||
this_month_bullets = []
|
||||
if month_rows:
|
||||
new_notable = [d for d in month_rows if d.get("seniority") in _NOTABLE_SENIORITIES]
|
||||
if new_notable:
|
||||
names = ", ".join(f"{d.get('name', '')} ({d.get('company', '') or d.get('seniority', '')})"
|
||||
for d in new_notable)
|
||||
this_month_bullets.append(
|
||||
f"{len(new_notable)} new notable contact{'s' if len(new_notable) != 1 else ''} "
|
||||
f"joined this month: {names}.")
|
||||
if clusters:
|
||||
from collections import Counter
|
||||
month_companies = Counter(d.get("company", "").strip() for d in month_rows
|
||||
if d.get("company", "").strip())
|
||||
grown = [f"{c} ({total_n} total, {month_companies[c]} new this month)"
|
||||
for c, total_n in clusters if month_companies.get(c)]
|
||||
if grown:
|
||||
this_month_bullets.append("Account clusters that grew this month: "
|
||||
+ "; ".join(grown) + ".")
|
||||
this_month_bullets = [html.Li(html.Strong(b), style={"marginBottom": "4px"}) for b in this_month_bullets]
|
||||
if not this_month_bullets:
|
||||
this_month_bullets = [html.Li(html.Em("No new notable contacts or growing account "
|
||||
"clusters this month."), style={"marginBottom": "4px"})]
|
||||
|
||||
overall_bullets = [
|
||||
f"Overall, {senior_n} of {total} ({senior_n / total * 100:.0f}%) sit at C-Level/Founder, "
|
||||
f"Director/Head/Principal, or Senior IC/Lead level, while {junior_n} "
|
||||
f"({junior_n / total * 100:.0f}%) are students or trainees — both ends of the "
|
||||
f"seniority range are represented, not just the middle.",
|
||||
@@ -3997,9 +4027,18 @@ def _follower_study_findings(whole, non_team, period_label):
|
||||
f"algorithmic surfacing rather than a direct personal tie.",
|
||||
]
|
||||
return dbc.Card([
|
||||
dbc.CardHeader(f"What {period_label}'s Followers Tell Us"),
|
||||
dbc.CardBody(html.Ul([html.Li(b, style={"marginBottom": "4px"}) for b in bullets],
|
||||
style={"fontSize": "0.85rem", "paddingLeft": "1.1rem", "marginBottom": "0"})),
|
||||
dbc.CardHeader(f"What Changed This Month vs. The Full Picture"),
|
||||
dbc.CardBody([
|
||||
html.Div(f"New this month ({period_label}):", style={"fontWeight": "700", "fontSize": "0.82rem",
|
||||
"marginBottom": "4px"}),
|
||||
html.Ul(this_month_bullets, style={"fontSize": "0.85rem", "paddingLeft": "1.1rem",
|
||||
"marginBottom": "12px"}),
|
||||
html.Div("The full picture, to date:", style={"fontWeight": "700", "fontSize": "0.82rem",
|
||||
"color": "#6b7a8d", "marginBottom": "4px"}),
|
||||
html.Ul([html.Li(b, style={"marginBottom": "4px"}) for b in overall_bullets],
|
||||
style={"fontSize": "0.85rem", "paddingLeft": "1.1rem", "marginBottom": "0",
|
||||
"color": "#6b7a8d"}),
|
||||
]),
|
||||
], className="mb-3 shadow-sm")
|
||||
|
||||
|
||||
@@ -4022,6 +4061,7 @@ def _follower_study_insights_page(month_value="2026-07"):
|
||||
if not d.get("followedSort") or d.get("followedSort") <= month_value]
|
||||
non_team = [d for d in directory_as_of_month if not d.get("is_team")]
|
||||
whole = follower_directory_data.composition_stats(non_team)
|
||||
month_rows = [d for d in non_team if d.get("followedSort") == month_value]
|
||||
|
||||
from collections import Counter
|
||||
companies = Counter(d.get("company", "").strip() for d in non_team if d.get("company", "").strip())
|
||||
@@ -4044,7 +4084,7 @@ def _follower_study_insights_page(month_value="2026-07"):
|
||||
], bordered=True, size="sm")
|
||||
|
||||
return dbc.Container([
|
||||
_follower_study_findings(whole, non_team, period_label),
|
||||
_follower_study_findings(whole, non_team, period_label, month_rows, clusters),
|
||||
dbc.Card([
|
||||
dbc.CardHeader(f"All {whole['total']} Followers to Date (through {period_label}), by "
|
||||
f"Sector, Function, Seniority and Country"),
|
||||
|
||||
Reference in new issue
Block a user