AI Growth Lead at Oneday since Feb 2025 · Previously Head of B2G Growth at AiCore · UK-based, fully remote
A revenue problem looks different from the boardroom, from the service map and from the code. I work at all three. Pick an altitude and follow one real problem through every level.
Click a level, or use the arrow keys.
I own the funnel numbers for the company and report them to leadership. The work is asking the question the dashboard can't answer, getting a clean read on it, and turning it into a decision somebody acts on this week.
Finding. Opt-outs spiked for leads in one US timezone. Lead volume and copy were unchanged.
Cause. The booking agent was offering early-morning slots in the lead's local time. People were being texted a 3am meeting.
Decision. No new copy, no new spend. Fix the slot logic at the source, audit every path that offers a time, and re-contact the affected leads with a human.
Each stage of the sale runs on software I built, integrated and operate. When something goes wrong, the question is which service, which rule, and who it touches, before anyone writes a line of code.
Rules in a document get forgotten. Rules in the type system don't. When a lead was offered a 3am slot, I didn't add a check. I made it so no code path can offer a slot that hasn't passed the daytime filter.
// A slot that has passed the lead-local daytime filter. Nothing else can be one. type DaytimeSlot = Slot & { readonly __daytime: unique symbol }; export function pickOfferSlots(pool: Slot[], lead: Lead): DaytimeSlot[] { const tz = resolveLeadTimezone(lead); // area-code inference when unknown return pool .filter(s => hourIn(s.start, tz, 8, 21)) .map(brand); } // Every sender takes the branded type. An unfiltered pool is a compile error. export function sendSlotOffer(lead: Lead, slots: DaytimeSlot[]) { /* … */ }
The company sells a degree programme. A lead talks to a salesperson, then an expert, then has a final call, pays, completes an application, and is enrolled with the partner college. Where a dashboard existed I replaced it with a system that acts. Where nothing existed, I built it.
Two agents, two calls. The first texts a new lead and books the first sales call. The second picks up once the lead is accepted and books the final call, across several phone numbers. Before them, 53% of lead messages went unanswered by reps.
Salespeople, the experts who take the second call, and the finance team each get their own dashboard. Call transcripts are joined to CRM outcomes, scored by an LLM against a rubric I developed on real calls, and turned into specific coaching actions.
After payment, every student had to be enrolled with the partner college. That used to mean staff chasing documents over email, re-keying them into the college's system by hand, and nobody knowing where any application stood. I replaced the process end to end.
Student emails documents to a staff member
Staff re-key details into the college's system
Status chased by email, one student at a time
Missed steps found at enrolment deadline
Student uploads and completes steps in the portal
Records sync to the college's system automatically
Status visible to student and staff, chasers automatic
Missing steps flagged the day they are missed
Reporting rebuilt so lead-to-enrolment is measured one way. Then a layer that watches the systems themselves, because a scheduled job that says "succeeded" can still be doing nothing.