Case study · Political campaign

Three days before the election, eight hours to the first door

A county-level campaign in southeast Iowa called three days out from polls opening. They had the same voter file as everyone else, a fraction of the budget, and no way to get either into a volunteer's hand. We turned that file into a field app their team used at the door, on their own phones, without paying per seat for a canvassing platform.

Delivered as a Flutter app for Android and iOS. The engagement is complete.

8 hrs
from brief to app in the field
15,745
active voters loaded
22
precincts covered
0
bars of signal required

The problem

Every campaign in the county can download the same voter export. Turning it into something a volunteer can carry down a street is the hard part, and it is usually solved by renting a commercial canvassing platform for the cycle.

This campaign wanted the targeting without the per-seat bill, and it needed to work in places where phones lose signal. The raw file makes that awkward: 137 columns, duplicated headers, and a vote history that records only the elections someone turned out for, with no marker for the ones they skipped.

What we built

An importer that survives a government export

The Secretary of State file arrives with 137 columns, repeated headers and vote history smeared across five columns per election type. The importer reads it by position rather than by name, then normalizes it into household, voter and vote-history tables, keeping the full original row as JSON so nothing is lost.

Walk books ordered the way people actually walk

Voters are grouped into households, so a door is knocked once rather than once per registered voter. Routes run street by street, up the odd side and back down the even side, with unnumbered addresses last.

Targeting the campaign could defend

Each voter gets a 0–100 propensity score from the generals they actually voted in, weighted toward recent elections and adjusted for whether they were old enough to vote at the time. Volunteers filter by party, minimum score, or super-voters only.

Built for basements and back roads

The whole voter file lives on the phone in a local database. Canvassers record results at the door with no connection, and each result carries an identifier so it can sync later without duplicating.

The call that made the scores trustworthy

The obvious way to score turnout is to compare elections voted against elections since someone registered. On this file it would have been wrong. The registration date is a re-registration date, so anyone who moved or updated their record looks like a perfect voter who simply had fewer chances.

Scoring that way pushed 67% of the county into the top band. Scoring against each voter's actual eligibility, worked out from their age at each election, put 56% there instead. The second number is the believable one, and it is the difference between a list that sends volunteers to the right doors and one that flatters everybody.

This is the part of the work that does not show up in a feature list: knowing which field in a government export means what it appears to mean.

What we deliberately did not build

Eight hours is not enough time to build everything, which turns out to be the point. With polls opening in three days, every hour spent on a feature was an hour not spent on doors, so the only question worth asking was what a canvasser touches standing on a porch.

So there is no analytics dashboard, no admin console, no role hierarchy, no real-time map of volunteers. The app imports the file, groups voters by household and precinct, orders the doors, works without signal, and records an outcome in one tap. That is the whole of it.

Anything else would have been a feature nobody had time to learn, competing for attention with the job in front of them. Scope discipline was not a compromise forced by the deadline — it was the thing that made the app usable by volunteers who got no training.

Where the voter data lived

The voter file stayed on the devices that needed it. It was never committed to the code repository, and the app does not need a connection to work, so a canvasser carries the data and nothing else does.

Door results are written locally with their own identifiers, so syncing them to a shared backend later cannot create duplicates.

The outcome

The campaign reports that its candidate won and that it carried the majority in every precinct its team canvassed with the app. Across the three-day canvassing push that followed delivery, it measured a 30% increase in votes for its candidate. It also spent far less on voter-contact tooling than the opposing campaign did.

Those results are the client's own account of their race, measured over their own three-day window, not figures we produced — and an election turns on far more than the tool a team knocks with. What we can show is the app: the import, the routing, the scoring, and the fact that it all ran offline in the field, three days after the first call.

  • A working app in the field the same day the brief arrived
  • A full county voter file, usable on a volunteer’s own phone
  • Households grouped so nobody knocks the same door twice
  • Turnout scoring the campaign could explain and defend
  • No per-seat platform fee for the cycle

Have a data set nobody can use yet?

Exports, spreadsheets and legacy systems are usually one good model away from being the thing your team works from. Bring yours to a working session.