//Outreach
Polls by text
Facts checked against official sources · September 9, 2026
A poll by text is a short survey delivered the way a local voter will actually answer it: a text that asks permission, a personal link sent only after they reply YES, and a one-question-per-screen form that saves every answer as it is given. Responses are stored against the voter record, so a result is not just a topline; it is a list of people who told you what they think.
Polls live under Outreach → Polls. The candidate and campaign managers build, send, and export; staff can read results. The survey itself is served from a neutral research domain, countypolls.org, rather than from the campaign platform, for reasons explained below.
What it is
A poll has a name, a saved voter list, two messages, an optional A/B split, a texting window, and a set of questions. The first message (M1) is the invite and carries no link: it says who is asking, roughly how long the survey takes, and that replying YES gets the link and STOP opts out. The second message (M2) is sent automatically when a recipient replies YES and contains their personal survey link. Keeping the link out of the first text is deliberate; it is what keeps the invite from being filtered as spam and what makes the opt-in real.
A poll moves through draft, active, paused, and closed. Nothing is texted until you press Send invites on the poll page and confirm. Closing freezes the response set so weighting can run against a stable denominator; a closed poll can be reopened to paused if it was closed by mistake.
Building the instrument
New poll asks for the name, the list, the invite text (up to 320 characters, and it must contain STOP language or the server refuses it), the link text (which must contain the {{link}} merge field or recipients would never reach the form), whether to run an A/B split, and the questions. Questions are pasted as JSON, one object per question with a prompt, a kind, whether it is required, optional help text, choices for choice questions, and an optional ballot version. Seven kinds are supported: yes/no, a 1-to-5 rating, single choice, multiple choice, short text, long text, and number. A poll can hold up to 100 questions. For an instrument written by a pollster or consultant, Culper also has an import path that loads a JSON build of the questionnaire as a draft in one transaction.
On the poll page the instrument is editable in place: add a question, edit its prompt, help text, required flag, ballot version, and choice labels, move it up or down, or delete it. The rules get strict once real answers exist, because an answer set cannot be re-collected. A question’s kind cannot change once it has answers. A choice value that has been answered cannot be removed or renamed, though its label stays editable. A question with answers cannot be deleted. The A/B split cannot be flipped once recipients exist, because each recipient already carries a ballot version. A closed poll is frozen entirely.
Recipients
Recipients are built from the list when the poll is created, and more can be added later from any other list; loading is additive and never removes anyone. The filter is aggressive on purpose. A voter becomes a recipient only if they are on the current county roll, have a phone that is not a landline, and that phone is a real 10- or 11-digit number (the guard exists because blank and garbage values otherwise slip through). Numbers are stored in one canonical form. A shared household number is texted once, with the reply attributed to one voter, so a couple with one cell phone is not invited twice. Any number on the global suppression list loads as opted out and is never texted. Each recipient gets an unguessable token that becomes their survey link.
Before you load a list the page previews the arithmetic: how many are on the list, how many are ineligible (off roll, no phone, or landline), how many had no usable mobile, how many were merged as a shared household number, how many are already on the poll, and how many will be added. The lines are required to sum to the total, and if they ever do not, the preview says so in red rather than letting voters vanish quietly.
Sending invites, quiet hours, and the YES loop
Send invites opens a confirmation that states how many numbers will be texted, requires a checkbox attesting that the send is authorized including the consent posture for that voter universe, and requires typing SEND. Before anything goes out, Culper checks the sending line live with Twilio: the line must have a verified A2P 10DLC campaign attached at that moment, and a stored “approved” status is not trusted. The first 25 invites send inline so you see real counts immediately; the rest drain in batches of 50 in the background until nothing pending remains.
Every batch re-checks suppression, and every recipient is claimed before the send so a re-run can never text the same person twice. Invites only go out between 8am and 9pm in the recipient’s local time, resolved from their coordinates, ZIP, and area code; a narrower window can be set per poll, and a recipient whose time zone cannot be resolved is treated as outside the window. Anyone deferred by quiet hours stays pending, and pressing Send again later picks them up.
Replies land on a dedicated, signature-verified poll webhook. YES (and Y, YEAH, YEP, SURE, OK, OKAY, START) marks the recipient opted in and sends the M2 text with their link; a second YES simply re-sends the link. STOP (and STOPALL, UNSUBSCRIBE, CANCEL, QUIT, END, REVOKE) writes the number to the global suppression list and marks every open poll invite for that number opted out. Anything else is ignored. The poll sends from a pinned number, not a pool, so a voter’s YES always reaches the poll webhook rather than a texter’s inbox.
- A poll can send from a dedicated poll line connected to the campaign, or inherit the campaign’s registered SMS service.
- Send a test texts the invite to any number you type, walks the full YES-to-link-to-form loop, and keeps that number’s answers out of the results. It works on a draft poll, so you can rehearse before anything is live.
- Pause stops new invites without locking out anyone mid-form. Close freezes everything.
The survey and the neutral domain
The link a recipient gets is countypolls.org/s/ followed by their token. It goes to a separate research domain rather than the campaign platform because a voter deciding whether an unsolicited text is legitimate reads a plain civic domain very differently from a software company’s, and carriers filter on the same signal. The page shows the CountyPolls identity, a progress bar, and one question at a time; it never shows the poll’s internal name or the campaign. Link previews are locked to the CountyPolls card so a forwarded screenshot reveals nothing, and every survey URL is marked not to be indexed because each one is a per-recipient secret.
Someone who strips the URL back to the bare domain lands on a page that answers the three questions a suspicious recipient has: who is asking, what happens to the answers (confidential, used for research, never sold), and how to stop (reply STOP). There is no signup and no marketing on it.
The form saves each answer the moment it is given, so a voter who quits at question 20 of 37 has still left 20 usable answers, and reopening the link resumes at the first unanswered question. Optional questions can be skipped; required ones cannot. The first saved answer counts as opting in, and finishing marks the recipient completed. An opted-out number sees an opt-out notice; a closed poll shows a closed notice.
Results and how they feed targeting
The poll page shows the funnel as tiles: pending, invited, opted in, partial, completed, opted out, and failed. Partial is the number of people who answered at least one question but did not finish; their answers are saved and already counted. Under the instrument, each question shows its response count and raw toplines as bars, with test answers shown separately and never mixed in.
Toplines are unweighted by design. Export CSV produces a long-format file with one row per answer: the state voter ID, the internal voter ID, ballot version, invite status, completion time, question position and prompt, and the answer. Joined to your universe file, that is the input a pollster needs to rake to age, gender, party, and vote history and produce weighted toplines and crosstabs. Because every response is keyed to a voter record, the same export is a targeting list: the people who said undecided on the ballot question are a set of names, not a percentage.
How a local campaign uses it
County office, message test. A consultant hands you a 37-question instrument with an A/B ballot. You import it, attach a 2,500-person sample from your list, and the preview shows 2,180 will be added after landlines and shared numbers drop out. You send a test to your own phone, walk the loop, then send for real at 10am. Deferred west-of-the-county numbers go out when you press Send again after lunch. Three days later you close the poll, export, and rake.
School board, bond question. Five questions: a yes/no on the bond, a 1-to-5 on the district’s direction, a single-choice top issue, and two short-text follow-ups. Sent to 900 parents on a saved list, with the A/B split off. Toplines are on the page the same evening, and the 140 people who answered no on the bond become a persuasion list.
City council, quick ballot check. Three questions to 1,200 likely voters two weeks out: the ballot, a favorability rating, and one open-ended “what would change your mind.” The open-ended answers are read raw; the ballot cut is exported and matched back to the walk list so undecideds get a door knock.
Why it matters
Professional polling is priced for statewide races; a council or school board campaign almost never has real data on its own electorate. A poll by text costs what the texts cost, and because it runs on your own list, the sample is the people who will actually vote. Turning a win number into the universe you should be polling and persuading is covered in How many votes does it take to win a local election.
It is still texting, and the rules apply in full: registration, opt-out handling, quiet hours, and consent. Culper enforces the first three in code and puts the consent attestation in front of you on every send. The rules themselves are in Political texting rules: TCPA and 10DLC.
What it does not do
The current build is the invite-and-web-form model. The things below are either deliberate boundaries or not built yet.
- No weighting in the app. Toplines are raw; weighted results come from the CSV export and your own raking step.
- Answers are collected on the web form, not by text reply. A voter cannot answer question 3 by texting “B.”
- No “save respondents as a list” button yet. Use the export, which carries the state voter ID, to build the list.
- No automatic reminder texts to people who were invited but never replied.
- Quiet-hours deferrals wait for you to press Send again; the drain does not wake itself up when the window opens.
- The sponsor named on the countypolls.org landing page is set by Culper for the current research program, not per campaign.
- Consent posture is attested by you at send time. Culper enforces suppression and can enforce a per-recipient consent check; it does not decide what consent an imported universe carries.
Works with
Polls borrow their audience, their registered line, and their opt-out handling from the rest of the platform.
- SMS outreach for A2P registration and the messaging service a poll sends through.
- Peer-to-peer texting, which can share the same registered line.
- Search, lists, and tags to build the sample and to act on the results.
- Scripts and surveys for the same question types captured at the door.
- Compliance and data security for the suppression list and consent log.
- Dashboard and reporting for where poll results sit next to everything else.
Frequently asked questions
Why do survey links go to countypolls.org instead of the campaign?
Because the recipient is deciding in about a second whether an unsolicited text is legitimate, and a plain civic research domain reads very differently from a campaign software site; carriers filter on the same signal. The survey page shows only the CountyPolls identity, never the campaign or the poll’s internal name, and the bare domain explains who is asking and how to stop.
Why does the first text not include the link?
A link in a cold text is the strongest spam signal there is, and it turns an invitation into a push. The invite asks for a YES; only then does the second text deliver a personal link. The opt-in is real, the deliverability is better, and the YES itself is recorded on the recipient.
Who becomes a recipient when I load a list?
Voters on the current county roll with a usable mobile number: landlines are excluded, malformed numbers are dropped, shared household numbers are texted once, and anyone on the suppression list loads as opted out. The preview shows every one of those subtractions before you commit, and the lines must sum to the list total.
What happens to someone who quits halfway through?
Every answer is saved the moment it is given, so a partial respondent’s answers are already in the toplines and the export. The poll page counts them under Partial. Reopening the link resumes at the first unanswered question.
Can I get weighted results?
Not inside the app yet. The page shows raw, unweighted toplines. Export the CSV, which carries the state voter ID and ballot version per answer, join it to your universe file, and rake to the marginals your pollster specifies. That is the workflow the current build was designed around.
What are the texting hours for poll invites?
8am to 9pm in the recipient’s local time, always, resolved from coordinates, ZIP, and area code; a poll can set a narrower window but never a wider one. Recipients outside the window when you press Send stay pending and go out the next time you press Send inside the window.
Ask your voters, not a national sample
Keep reading