Skip to content

Research

A Research record is LeadHunter’s audit trail for how an account got into your database. Every Google Maps sweep, CSV import, URL lookup, AI enrichment pass, and operator-logged manual research session has its own row — so months later you can answer “why do we have this account, who put it there, what method was used, and what did it cost?”

Research is the audit-trail equivalent of status_history on the account itself — but for discovery, not lifecycle.

The Find new accounts page (the Find new accounts button at the top of the Accounts page) is the home for the log. It shows:

  • Counts — total research, in progress, completed, failed.
  • A filterable list of every research record in the active project, newest first, with status, method, result counts, and the user who triggered it.
  • A New Research action that starts a Google Maps API or Tavily AI Search run, or logs research you did yourself (Manual Entry) — useful when discovery happened outside LeadHunter (a directory you bought, a trade-show booth scan, a vendor list) and you want the record for accounting and team visibility.
MethodTriggerUI surface
Google Maps searchSearch terms like “bike shops” plus countries / cities.Find new accounts → New Research → Google Maps API
Tavily AI searchAI web search that finds businesses across the internet.Find new accounts → New Research → Tavily AI Search
Google Maps URLPaste a maps.google.com/... URL.Accounts → Add account → From URL
Website / domainPaste acme.com or a full URL — LeadHunter scrapes it.Accounts → Add account → From URL
CSV / XLSX importUpload a spreadsheet through the import wizard. One research record per file.Accounts → Import
AI deep researchOptional follow-up pass that fills missing fields and writes salesperson notes.Accounts → Add account → From URL, Deep mode
EnrichmentWebsite discovery + scrape for a set of accounts.Accounts → More → Enrich, and the optional enrich after an import
Manual research logYou did the discovery yourself; you’re recording it.Find new accounts → New Research → Manual Entry

The method field on the record captures which path produced it: manual, google_maps_api, tavily_research, web_scraping (enrichment), csv_import, api_integration, other. (apollo_enrichment appears on old records only; Apollo isn’t available as a method.)

BucketFields
Identityname, description, method, status
Executionstarted_at, completed_at, duration_seconds, executed_by
Tooling (automated runs only)script_name, script_version
Search parameterscountries, cities, search_terms, search_radius_meters, instructions, configuration
Resultstotal_items_found, new_items_added, items_updated, duplicates_found, errors_count
Costapi_calls_made, estimated_cost (USD)
Provenancesource_files, notes, error_log, created_by, created_at, updated_at

Search-parameter fields (countries, cities, search_terms) make it easy to re-run a discovery later: a Google Maps sweep done six months ago records exactly what was searched, so a fresh sweep with the same terms is one click away to catch new businesses.

A research record moves through five states:

  1. planned — created but not started yet. Multi-step wizards (CSV import column-mapping, complex Maps queries) hold the research here while the operator configures it.
  2. in_progress — the discovery / scrape / enrichment is actively running. Long imports stay here for minutes.
  3. completed — finished successfully. Result counts and cost are populated.
  4. partial — finished with errors but produced some results. The error_log records what went wrong; the results that came through are on accounts.
  5. failed — couldn’t produce useful results (Google Maps quota exhausted before the first hit, the CSV was malformed, the website refused to scrape). The error is recorded so you can read it and decide whether to retry.

Only methods LeadHunter can run itself — Google Maps API, Tavily AI Search and enrichment — can be started (row menu → Start execution). A Manual Entry record (and the other non-automated methods) is a log of work done outside LeadHunter: starting it is refused with “…research has no automated runner, so it can’t be started. Add the accounts it found by hand instead.” It stays planned until you record what it produced.

Forward-only: a research record doesn’t go back to planned once it’s started running. Status moves through the run itself (start, complete, fail, cancel) — it can’t be set by editing the record, and a new record always starts as planned.

For automated runs the outcome follows what actually happened: a Google Maps or Tavily run is completed when every search succeeded, partial when some searches failed, and failed when none did.

Research records are the Imports, enrichment and searches section of Runs (sidebar → Runs), next to Campaign scoring and Ranking runs, which aren’t research records. Each row shows progress, cost and View results; a running one can be cancelled.

Retry on a failed row of the Runs page creates a copy of the run with the same parameters and starts it as a new run (“Run restarted as a new run.”); the failed record stays as it was, for the audit trail. It works for Google Maps, Tavily and enrichment runs (an enrichment retry re-runs the same accounts). A CSV import can’t be retried — the uploaded file isn’t kept — so a failed import shows Re-import the file instead of Retry: upload the file again from Accounts → Import.

Before a research run creates an account, it checks the project for a duplicate (see what happens on a match):

  • Google Maps checks the Google Place ID only. A place already in the project is not added again.
  • Tavily checks name + city, phone, website domain and similar names in the same city. Any match drops the result.

Nothing is merged: a result is either created as a new account or skipped as a duplicate, and the existing account is left as it was. Because Google Maps only checks the Place ID, a business you already had without one (from a file import, for example) can come back as a second account — run Find duplicates (Accounts → More) after a big run.

The research record’s counts reflect that split:

FieldWhat it counts
total_items_foundEverything the discovery produced (before the duplicate check).
new_items_addedNew accounts created.
duplicates_foundResults skipped because the account already exists.
items_updatedGoogle Maps only: a place whose account appeared while the run was going (from another run or import) and was refreshed with the Maps details. Usually 0.
errors_countItems that hit a per-row error (malformed input, scrape failed, …) — see error_log.

So a quick scan of “discovered 142 places, 87 new, 55 already in the project, 0 errors” tells you what the run added.

A CSV import records the same split and keeps the detail: its result panel (in the import dialog) offers Rows not imported and Duplicates skipped as CSV downloads (every skipped row, with the account each duplicate matched), and View these N accounts opens the Accounts list filtered to exactly the accounts that import created (a From import chip). See Import accounts.

External calls cost money — Google Maps charges per place lookup, Tavily charges per search, every LLM call burns tokens. Each cost is auto-attributed to the research record that triggered it, and the Runs page (sidebar → Runs) shows a per-row Cost column with the USD total and total tokens used:

$0.0234 · 12.4k tok

Hover the cell for the per-model breakdown:

Total: $0.0234 · 18 calls
Tokens: 11.2k in / 1.2k out
openrouter:openai/gpt-6-luna: $0.0180 · 12 calls · 11.2k tok
google_maps: $0.0054 · 6 calls

Use the column to spot a run that cost more than it should have (a website that needed the LLM fallback for every account, an enrichment job that scraped a few thousand pages), and the model breakdown to see which part of the work was expensive — Google Maps Places lookups, the default AI model (gpt-6-luna through OpenRouter since 3 October 2026; website discovery uses Gemini with Google Search), or a costlier model swapped in for a specific run.

For the cross-research breakdown (provider totals, daily trends, per-research-record-comparison views), see Usage and costs — Insights → Usage shows all of it on one screen.

Manually-entered campaign expenses (Adwords, agency fees, labor hours) don’t flow into research records — those attach to campaigns instead, since they’re paying for a specific outbound effort, not for one batch of discovery. See Track campaign costs and CAC for that side.

  • A weird account showed up in a campaign — open the account, check the source field, and trace back to the research record. Useful when you don’t remember which import dropped it in.
  • You want to work only what one import brought in — View results on its Runs row (or View these N accounts on the import result) filters the Accounts list to that batch, ready to Rank or add to a campaign.
  • You ran a Google Maps sweep months ago and want to re-run the same query to catch new businesses. The search_terms, countries, and cities fields on the old research record carry exactly what you searched.
  • You’re auditing AI cost spend and want per-discovery attribution — sort by estimated_cost desc.
  • An import partially failed (status='partial'). Open the record, read error_log, decide whether the errors are retryable.
  • Import accounts — the three discovery / enrichment paths in detail.
  • Account — the row that research produces.
  • Merge duplicates — what happens to fuzzy candidates a research record surfaces.
  • Usage and costs — the cost surface research records contribute to.