← All projects

Positioning Lab

Prototype

Compares customer segments for an independent practice and reports what the available evidence can support.

FreelanceWeb AppPythonFastAPIPostgreSQLClient Work

At a glance

  • Outcome: Identifies a testable segment.
  • Status: Concluded late August 2026; last commit was August 28. From July 19, 2026: 420 commits across 25 working days, 2,221 collected tests and 117 numbered decision records. After August 27 consolidation, 23 remained in the tree; an invite-only Dokku demo ran four screens end-to-end with live Meta and recorded search data.
  • Role: Built solo through my LLC contract, focused on data plumbing.
  • Stack & libraries: FastAPI, SQLAlchemy 2, PostgreSQL/psycopg 3, Jinja2 templates, one inlined built Tailwind stylesheet, httpx for every source, Playwright Chromium for PDFs, Pydantic settings, uv lockfile, ruff and pytest. Deployed the Docker image by tarball to Dokku behind a startup healthcheck; used a Nix dev shell. GitHub Actions ran lint, format checks and tests. Declared RQ, Redis and Alembic without importing them; jobs stay in-process and seeds create the demo schema pending their first real callers.
  • Source: Private client case study.
  • Limitations: No practitioner completed the 90 days required to name a winner. Google uses Keyword Planner transcriptions because the developer-token tier rejects the required planning call; Bing covers eleven recorded markets. Search Console has an unmounted adapter and fixture.

Scope

Replaced a working drive-time and demographics version when golf, desk work, cycling and postpartum produced one age, income and population result despite four channels. Preserved it at a tag. Now tests whether a practitioner can test a customer in that market, not market size.

Workflow

Resolve an address, county or state through the Census geocoder and ZIP-to-county crosswalk, then confirm the market. Choose three to five of 145 segments in 19 activity communities. Promote exact Meta interest names and ids as a dated artifact; exclude 24 search collisions by name.

Isolate source sessions so one fault preserves other results. Split reach into four age bands and two genders per column. Report available and missing results; produce one reasoned campaign-sheet setting per segment. Query Meta live in 202 markets through ten-mile lead-city radii because it provides no market geography; disclose that limit beside every reading.

Replay recorded Bing sittings and dated Google Keyword Planner UI transcriptions. Count local access from a promoted OpenStreetMap extract with authored tag rules; the previous grouping counted a tennis shop as a running place.

Subject provenance

Store source and subject separately. One human-authored row maps each concept to the ad platform, both search networks and facility data. Infer nothing; distinguish unasked sources from those without terms.

The first live recorder lacked the application’s first-result guard, matching “runners” to Pop music of the 1980s and storing five audience measurements. Their folder identifies the error and prohibits market attribution.

Generate search phrasings with a model; use a classifier and record that model. The first roster-wide run made 293 attempts and admitted 6,348 Bing and 6,597 Google phrasings. Reject terms not admitted by the cited attempt, changed digests and false human attribution; people author in one file. Across eleven markets, only 1.4 to 12.6 percent returned volume; record absence instead of zero.

Measurement rules

Assign figures to sixteen universes: search volume, ad reach, residents, households, facilities, referrers, establishments, prevalence, practitioner books and seven more. Reject combined universes; treat each search network separately.

Place each candidate in one bucket; order only passers per lane. Produce no combined ranking or score.

Meta ranges are fifteen percent wide; every recorded lower bound equals the upper bound times 0.85. Width represents presentation, not uncertainty. Treat audiences within fifteen percent as indistinguishable. Tests preserve golf, running and cycling ties in four of five markets and the fifth market’s distinction.

Validation

The first recorded reach run returned no ordering. Only the practitioner’s wording had data, but awaited review; released segments lacked measured gates. Kept the result and chose evidence to record.

The first eleven-market Bing sitting found 1,744 of 6,135 rows matching only by case. Exact matching dropped 145 of one market’s 358 rows as unasked and absent. Casefold matching retains requested spelling; replaying the same bytes corrects the count.

Tests require exactly eleven domain modules and prohibit their web or job imports. They require organization context first for services and repositories, block unscoped access and resolve every ADR path locally or at a named git ref.

Ended append-only records on August 27. Consolidated 106 ADRs into a rewritten design and twenty core decisions. Replace decisions in place, retain their reasoning under alternatives and never reuse numbers because roughly eight hundred citations reference them.