You've shipped group_by_channel, channel_summary, load_campaigns_from_csv, campaigns_to_json. Each one works. What's still missing before your CMO can run this on Monday?
They're not connected. I can parse a CSV, I can group campaigns, I can serialise the output — but I'm still wiring them together by hand every time. It's like having all the VLOOKUP formulas but no master tab that calls them.
That's exactly the Week 4 problem. Composition and robustness. This week you stop writing isolated functions and start chaining them — filter with a comprehension, rank with sorted, wrap the CPL formula in try/except so messy rows don't crash the whole report, then assemble it all in quarterly_report. Campaign exports are never clean in practice: a missing leads field throws a KeyError, a zero throws a ZeroDivisionError, a spend that came through as "12,400" throws a ValueError. One bad row shouldn't wipe out the other thirty-nine — try/except is the IFERROR you already know, just composable.
So quarterly_report is basically the master tab — it calls everything and gives back one clean dict I can email or paste into Slack.
Exactly. And it's the function your VP of Marketing will ask to run on last quarter's actual data once they see the output.
top_campaigns_by_cpl: list comprehension as filter + transform in one lineextract_campaign_names: re.findall + strip + clean_campaign_name in sequencerank_channels_by_cpl: group_by_channel → avg CPL → sorted(key=lambda)safe_compute_cpl: try/except KeyError, ValueError, ZeroDivisionError — the IFERROR that composesquarterly_report: full pipeline capstone — ranked channels, flagged underperformers, one dictGoal: a self-contained report function that replaces 8 hours of weekly manual Excel work.
7 lessons this week
You've shipped group_by_channel, channel_summary, load_campaigns_from_csv, campaigns_to_json. Each one works. What's still missing before your CMO can run this on Monday?
They're not connected. I can parse a CSV, I can group campaigns, I can serialise the output — but I'm still wiring them together by hand every time. It's like having all the VLOOKUP formulas but no master tab that calls them.
That's exactly the Week 4 problem. Composition and robustness. This week you stop writing isolated functions and start chaining them — filter with a comprehension, rank with sorted, wrap the CPL formula in try/except so messy rows don't crash the whole report, then assemble it all in quarterly_report. Campaign exports are never clean in practice: a missing leads field throws a KeyError, a zero throws a ZeroDivisionError, a spend that came through as "12,400" throws a ValueError. One bad row shouldn't wipe out the other thirty-nine — try/except is the IFERROR you already know, just composable.
So quarterly_report is basically the master tab — it calls everything and gives back one clean dict I can email or paste into Slack.
Exactly. And it's the function your VP of Marketing will ask to run on last quarter's actual data once they see the output.
top_campaigns_by_cpl: list comprehension as filter + transform in one lineextract_campaign_names: re.findall + strip + clean_campaign_name in sequencerank_channels_by_cpl: group_by_channel → avg CPL → sorted(key=lambda)safe_compute_cpl: try/except KeyError, ValueError, ZeroDivisionError — the IFERROR that composesquarterly_report: full pipeline capstone — ranked channels, flagged underperformers, one dictGoal: a self-contained report function that replaces 8 hours of weekly manual Excel work.