<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Isa</title>
    <description>The latest articles on Forem by Alex Isa (@alexisa).</description>
    <link>https://forem.com/alexisa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3843231%2F9bdd19e4-8c1a-4273-9a4b-52804bc9e69d.jpg</url>
      <title>Forem: Alex Isa</title>
      <link>https://forem.com/alexisa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alexisa"/>
    <language>en</language>
    <item>
      <title>Free Open-Source AEO Tracker: Our Real Score Was 33/100</title>
      <dc:creator>Alex Isa</dc:creator>
      <pubDate>Mon, 27 Apr 2026 07:48:55 +0000</pubDate>
      <link>https://forem.com/alexisa/free-open-source-aeo-tracker-our-real-score-was-33100-258i</link>
      <guid>https://forem.com/alexisa/free-open-source-aeo-tracker-our-real-score-was-33100-258i</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://www.npmjs.com/package/@webappski/aeo-tracker" rel="noopener noreferrer"&gt;&lt;code&gt;@webappski/aeo-tracker&lt;/code&gt;&lt;/a&gt; is an open-source Answer Engine Optimization (AEO) tracker — a Node.js CLI that measures brand visibility on ChatGPT, Gemini, Claude, and Perplexity via official APIs.&lt;/strong&gt; Free, MIT-licensed, ~$0.20 per weekly run, zero runtime dependencies. Open-source alternative to Profound, Otterly, Peec.ai, and HubSpot's AEO Grader — calls the real provider APIs (no web scraping), saves every raw response to disk for audit, and uses a two-model LLM cross-check on competitor extraction to filter hallucinated brand names.&lt;/p&gt;

&lt;p&gt;AEO (also known as GEO — Generative Engine Optimization) is the discipline of measuring and improving how often AI answer engines name your brand; this tool is the measurement half. Below: why we built it, the real numbers it gave us, the actual extractor code, and the quickstart.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I didn't pay for Profound, Otterly, or Peec.ai
&lt;/h2&gt;

&lt;p&gt;Every AEO tracker I tried gave me a different number for the same brand. &lt;strong&gt;HubSpot's free AEO Grader scored us 28 out of 100.&lt;/strong&gt; One paid dashboard said 44. A third refused to index the brand at all. A fourth was gated behind a $400-per-month plan before it would run a single query. None of them would show me the actual ChatGPT response they scored against.&lt;/p&gt;

&lt;p&gt;As an engineer, this was untenable. I needed an answer to two questions no vendor wanted to answer: &lt;strong&gt;(1) Are you actually calling ChatGPT, or are you scraping Bing and inferring?&lt;/strong&gt; ChatGPT's API uses its own grounding pool; Bing's SERP uses another. A "ChatGPT visibility score" derived from web scraping is not a ChatGPT visibility score. &lt;strong&gt;(2) What counts as a mention?&lt;/strong&gt; If my brand appears only in a cited URL but not in the answer text, do you count that?&lt;/p&gt;

&lt;p&gt;Nobody had documented answers. Profound, Otterly, and Peec.ai are closed-source dashboards with proprietary scoring layers; HubSpot's grader sits on top of a web-scrape pipeline that anyone can replicate but nobody publishes. "I walked away from all of them and built my own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three commands from install to HTML report
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @webappski/aeo-tracker
aeo-tracker init &lt;span class="nt"&gt;--auto&lt;/span&gt;
aeo-tracker run
aeo-tracker report &lt;span class="nt"&gt;--html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;init --auto&lt;/code&gt; fetches your homepage, asks an LLM to suggest category-appropriate queries, validates them with a second model, and writes a config.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;run&lt;/code&gt; calls each AI engine whose API key is set in your shell env. Model IDs are &lt;strong&gt;config-driven defaults you can override per-run&lt;/strong&gt; — current defaults in &lt;a href="https://github.com/DVdmitry/aeo-tracker/blob/main/lib/config.js" rel="noopener noreferrer"&gt;&lt;code&gt;lib/config.js&lt;/code&gt;&lt;/a&gt; are &lt;code&gt;gpt-5-search-api&lt;/code&gt;, &lt;code&gt;gemini-2.5-pro&lt;/code&gt;, &lt;code&gt;claude-sonnet-4-6&lt;/code&gt; and &lt;code&gt;sonar-pro&lt;/code&gt;; pass any other provider-supported model via &lt;code&gt;--model openai=…&lt;/code&gt; or by editing &lt;code&gt;.aeo-tracker.json&lt;/code&gt;. &lt;code&gt;report --html&lt;/code&gt; renders a Markdown report with inline SVG charts plus a fully interactive HTML dashboard.&lt;/p&gt;

&lt;p&gt;A few design choices that map directly to the frustrations above:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Direct API calls, nothing in between.&lt;/strong&gt; No web scraping. No browser automation. No proxied sessions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-flight query validation.&lt;/strong&gt; A separate LLM pass checks each query for ambiguity, acronym overload, and category drift before any tokens hit the engines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Raw responses saved to disk.&lt;/strong&gt; Every query × engine combination writes a JSON file under &lt;code&gt;aeo-responses/YYYY-MM-DD/&lt;/code&gt;. Any number in the report is auditable back to the exact AI reply.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero runtime dependencies.&lt;/strong&gt; &lt;a href="https://github.com/DVdmitry/aeo-tracker/blob/main/package.json" rel="noopener noreferrer"&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/a&gt; has no &lt;code&gt;dependencies&lt;/code&gt; and no &lt;code&gt;peerDependencies&lt;/code&gt; — &lt;code&gt;grep&lt;/code&gt; it yourself. The whole CLI, including the SVG renderer, is plain Node.js 18+. Auditable in an afternoon.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How does the two-model cross-check work?
&lt;/h2&gt;

&lt;p&gt;The core design decision in the tracker is how it decides which competitor brands an AI answer mentioned. Single-model extractors hallucinate routinely — they confidently return brand names that never appeared in the source response. The fix is to ask &lt;strong&gt;two cheap LLMs in parallel&lt;/strong&gt; to extract brand names from the same response, then merge their answers. Both agree → "verified" tier (solid badge in the report). Only one agrees → "unverified" tier (dashed badge). Neither → dropped before the merge.&lt;/p&gt;

&lt;p&gt;Here's the actual prompt the extractor sends — it's the file &lt;a href="https://github.com/DVdmitry/aeo-tracker/blob/main/lib/report/extract-competitors-llm.js" rel="noopener noreferrer"&gt;&lt;code&gt;lib/report/extract-competitors-llm.js&lt;/code&gt;&lt;/a&gt;, reproduced verbatim with comment headers stripped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Strict-JSON prompt. Identical for both models so responses are directly comparable.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildExtractorPrompt&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;categoryLine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;category&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`\nUSER CATEGORY: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nOnly names that are DIRECT ALTERNATIVES`&lt;/span&gt;
      &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;` to the user's offering in this category qualify as competitors.`&lt;/span&gt;
      &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;` Platforms/sources/publications mentioned as data or distribution`&lt;/span&gt;
      &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s2"&gt;` channels do NOT qualify.`&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`You extract COMPETITOR brand/product/agency names from an AI
answer-engine response.

The user's brand is "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" (domain: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;).&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;categoryLine&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

A COMPETITOR is a real company, product, or service that a buyer could
choose INSTEAD OF the user's brand, in the same category.

EXCLUDE (not competitors, even if mentioned as useful):
  - The user's own brand
  - AI-engines themselves (ChatGPT, Gemini, Claude, Perplexity)
    unless the user's category is "AI assistants"
  - Data sources / review platforms / social networks (Reddit, G2,
    Trustpilot, Quora, LinkedIn, Slack, Discord, YouTube, Wikipedia,
    TechCrunch, Wired, Yelp, Capterra) unless the user's category
    is "review platforms" or similar
  - Tooling unrelated to the category (Upwork, Toptal, Shopify, Zoom)
  - Metrics, KPIs, methodologies ("Citation Rate", "Share of Voice")
  - Process steps ("Build a Prompt Library", "Establish a Baseline")
  - Section headers ("Content Freshness", "Technical Optimization")
  - Names mentioned only as contrast ("Unlike X, we ...")

EXAMPLES:
  Category: "Answer Engine Optimization services"
    "Top AEO agencies: NoGood, Minuttia, Optimist"
      → brands: ["NoGood", "Minuttia", "Optimist"]
    "To get recommended by AI, get reviews on G2 and be mentioned on
     Reddit and TechCrunch"
      → brands: []   (G2, Reddit, TechCrunch are data sources)

  Category: "CRM software"
    "Leading CRMs include Salesforce, HubSpot, Pipedrive"
      → brands: ["Salesforce", "HubSpot", "Pipedrive"]

RULES:
  1. Return canonical form (original casing/punctuation from source).
  2. Do NOT invent names — every returned name must appear verbatim
     in the source text.
  3. Deduplicate.
  4. If nothing qualifies, return { "brands": [] } — being empty is
     correct and useful.

Return STRICT JSON, no markdown, no prose:
{ "brands": ["Name1", "Name2", ...] }

SOURCE TEXT:
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Hallucination guard — second line of defence after the merge step.&lt;/span&gt;
&lt;span class="c1"&gt;// Catches names a model invents that don't actually appear in the response.&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;filterHallucinations&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;brands&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sourceText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lowerSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sourceText&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;brands&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lowerSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The merge step is small but load-bearing: case-insensitive match on first-seen canonical form, both-model intersection becomes "verified", set-symmetric-difference becomes "unverified". A model that invents &lt;code&gt;HubSpot&lt;/code&gt; when the response never mentions it gets its invented entry silently filtered before merge — the verbatim-substring check catches it. Two models invent the same hallucination far less often than one does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a real AEO tracker output look like?
&lt;/h2&gt;

&lt;p&gt;This is the score card the tracker produced for our brand on 2026-04-23:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cdk1qzcp2e4guju1qpk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cdk1qzcp2e4guju1qpk.png" alt="AEO tracker overview — visibility score 33/100 PRESENT, 4 of 12 cells named brand, per-engine cards Claude 0%, ChatGPT 33%, Gemini 33%, Perplexity 67%" width="800" height="931"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;33 out of 100. PRESENT.&lt;/strong&gt; Four out of twelve query-engine cells named the brand. Three queries × four engines = twelve cells. Pre-revenue baseline range is 0–15; six-month-old brands with SEO investment land 20–45; category leaders are 60–85. The tool charts movement over months, not grades for today.&lt;/p&gt;

&lt;p&gt;Per-engine breakdown is where the real signal is: Perplexity 2/3 (strongest channel), ChatGPT 1/3 and Gemini 1/3 (one-each on different queries), Claude 0/3 (complete invisibility). Across our three test queries, Claude's grounding pool skewed toward dev.to, GitHub, and Product Hunt — domains where we don't yet have a footprint. Three queries, one category — treat it as a hypothesis to test on your own runs, not Anthropic policy.&lt;/p&gt;

&lt;p&gt;The position matrix is even more interesting because it shows &lt;strong&gt;who AI named instead of you on each query&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fenf585o255wlkz05d4x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fenf585o255wlkz05d4x2.png" alt="AEO tracker position matrix — three queries × four engines, with TypelessForm at #1 on Gemini and Perplexity for " width="800" height="989"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aggregated across all cells: TypelessForm 4 mentions, AnveVoice 3, Wispr Flow 2, Form2Agent 1, Dragon by Nuance 1, Voiceform 1. The top-cited canonical source AI engines linked to was &lt;code&gt;usevoicy.com&lt;/code&gt; — the same domain twice across two engines. One placement on &lt;code&gt;usevoicy.com&lt;/code&gt; would propagate across every engine that grounds in it. That's an outreach target, not a content target.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to run an AEO tracker on your own brand
&lt;/h2&gt;

&lt;p&gt;Two API keys, minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @webappski/aeo-tracker

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-proj-..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"AIzaSy..."&lt;/span&gt;

aeo-tracker init &lt;span class="nt"&gt;--yes&lt;/span&gt; &lt;span class="nt"&gt;--brand&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOURBRAND &lt;span class="nt"&gt;--domain&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YOURDOMAIN.COM &lt;span class="nt"&gt;--auto&lt;/span&gt;
aeo-tracker run
aeo-tracker report &lt;span class="nt"&gt;--html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That covers the ChatGPT and Gemini columns at roughly &lt;strong&gt;$0.20 per weekly run&lt;/strong&gt;. Add an Anthropic key for the Claude column (+~$0.30) or a Perplexity key for the Perplexity column (+~$0.05). Full four-engine coverage: ~$0.55 per run. Each provider's free tier is enough for the first month.&lt;/p&gt;

&lt;p&gt;After the first run, the workflow is two commands once a week: &lt;code&gt;aeo-tracker run &amp;amp;&amp;amp; aeo-tracker report --html&lt;/code&gt;. The HTML report auto-opens in your browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this open source instead of a SaaS?
&lt;/h2&gt;

&lt;p&gt;Because the measurement should be commodity. The interpretation and execution shouldn't.&lt;/p&gt;

&lt;p&gt;I'm not building this alone — the tracker is the open-source half of what my consulting agency does for clients. We run &lt;a href="https://webappski.com" rel="noopener noreferrer"&gt;Webappski&lt;/a&gt;, and a client who can independently run &lt;code&gt;aeo-tracker run&lt;/code&gt; and see their own raw numbers is a client who can check our work. We charge for the rest — the third-party placements, the comparison pages, the authority building, and the weekly read-out that turns numbers into action. The CLI handles measurement; everything that turns measurement into mention growth is the consulting half.&lt;/p&gt;

&lt;p&gt;If that's interesting: &lt;a href="https://webappski.com/en/aeo-services" rel="noopener noreferrer"&gt;https://webappski.com/en/aeo-services&lt;/a&gt;. If not: the tool is yours anyway. No telemetry, no analytics, no traffic to our servers. Your keys and your data stay on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How does it compare to Profound?
&lt;/h3&gt;

&lt;p&gt;Profound is a closed-source dashboard. &lt;code&gt;@webappski/aeo-tracker&lt;/code&gt; is an open-source CLI you install locally with &lt;code&gt;npm&lt;/code&gt;. Profound aggregates engine results behind a proprietary scoring layer; aeo-tracker exposes the raw AI responses and lets you compute the score yourself. Profound starts in the high-three-figure range monthly; aeo-tracker is free + ~$0.20 per run in API spend. Trade-off: Profound has historical dashboards and a sales rep; aeo-tracker has source code and a &lt;code&gt;git log&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How much does it cost to run?
&lt;/h3&gt;

&lt;p&gt;The tool is free under MIT. You pay only for the AI API calls you make with your own keys: ~$0.20 per run at the two-engine minimum (OpenAI + Gemini), ~$0.55 per run for four-engine coverage (adding Anthropic + Perplexity). Each provider's free tier is enough to start.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does a 33/100 score mean?
&lt;/h3&gt;

&lt;p&gt;It means 4 out of 12 query-engine cells named the brand in the answer text — three queries × four engines = twelve cells. The tracker counts how many returned a verified mention. Reference ranges: 0–15 for a pre-revenue brand at launch; 20–45 for a 6-month-old brand with on-page SEO; 60–85 for the category leaders. The score is a snapshot, not a verdict — week-over-week diff is where the tool earns its keep.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is "TypelessForm" — the brand the screenshots reference?
&lt;/h3&gt;

&lt;p&gt;TypelessForm is the brand we tested the tracker on. It's a one-shot voice form-filling widget — drop a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag on any HTML form and visitors can fill every field of the form by speaking one sentence. 25+ languages, GDPR-compliant, free tier. The product itself lives at &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;https://typelessform.com&lt;/a&gt; (the &lt;a href="https://typelessform.com/blog/voice-form-filling-hotel-booking" rel="noopener noreferrer"&gt;hotel-booking write-up&lt;/a&gt; is the fastest way to see what "one-shot" means). The tracker is a separate project from the widget — same maintainer, different repo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;npm: &lt;a href="https://www.npmjs.com/package/@webappski/aeo-tracker" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/@webappski/aeo-tracker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;GitHub repo: &lt;a href="https://github.com/DVdmitry/aeo-tracker" rel="noopener noreferrer"&gt;https://github.com/DVdmitry/aeo-tracker&lt;/a&gt; (star if useful — helps other developers find it)&lt;/li&gt;
&lt;li&gt;Full original article with all five tracker screenshots: &lt;a href="https://typelessform.com/blog/free-open-source-aeo-tracker" rel="noopener noreferrer"&gt;https://typelessform.com/blog/free-open-source-aeo-tracker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;AEO consulting (the human layer): &lt;a href="https://webappski.com/en/aeo-services" rel="noopener noreferrer"&gt;https://webappski.com/en/aeo-services&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Issues / PRs welcome: &lt;a href="https://github.com/DVdmitry/aeo-tracker/issues" rel="noopener noreferrer"&gt;https://github.com/DVdmitry/aeo-tracker/issues&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it and tell me what surprised you
&lt;/h2&gt;

&lt;p&gt;Run it on your own brand and &lt;strong&gt;post your engine breakdown in the comments — the Claude vs Perplexity diff is the most surprising part&lt;/strong&gt;. I want to see whether the 0/3 Claude blind spot is TypelessForm-specific or category-wide. Same pattern in your run? Fork the repo and let's debug it in an issue.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>llm</category>
      <category>aeo</category>
    </item>
    <item>
      <title>Best Ways to Add Voice Input to HTML Forms (JavaScript Guide, 2026)</title>
      <dc:creator>Alex Isa</dc:creator>
      <pubDate>Wed, 01 Apr 2026 09:59:11 +0000</pubDate>
      <link>https://forem.com/alexisa/best-ways-to-add-voice-input-to-html-forms-javascript-guide-2026-1192</link>
      <guid>https://forem.com/alexisa/best-ways-to-add-voice-input-to-html-forms-javascript-guide-2026-1192</guid>
      <description>&lt;p&gt;Typing into forms is still one of the worst UX patterns on mobile.&lt;/p&gt;

&lt;p&gt;Small keyboards, multiple fields, constant switching between inputs — it’s slow, frustrating, and error-prone.&lt;/p&gt;

&lt;p&gt;So what are the actual options if you want users to &lt;strong&gt;fill forms using voice instead of typing&lt;/strong&gt;?&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;There are two main ways to add voice input to web forms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the Web Speech API → gives you raw transcription, but you need to build everything else
&lt;/li&gt;
&lt;li&gt;Use a ready-to-use voice form widget (e.g. TypelessForm) → automatically fills all form fields from a single spoken sentence
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want full control, use APIs.&lt;br&gt;&lt;br&gt;
If you want speed and simplicity, use a drop-in solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The easiest way to add voice input to an HTML form today is to use a drop-in JavaScript widget that handles speech recognition and form autofill automatically.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For most real-world use cases, a voice form widget is currently the most practical solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Category Is This?
&lt;/h2&gt;

&lt;p&gt;These tools belong to a category often referred to as &lt;strong&gt;voice-to-form&lt;/strong&gt; or &lt;strong&gt;speech-to-form input&lt;/strong&gt; — where users provide structured data by speaking naturally instead of typing field by field.&lt;/p&gt;

&lt;p&gt;This category is still emerging, but it’s becoming relevant for mobile-heavy workflows and long-form inputs.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;The challenge is not capturing speech — it's turning natural language into structured form data and mapping it correctly to multiple fields.&lt;/p&gt;

&lt;p&gt;Capturing voice is relatively easy.&lt;/p&gt;

&lt;p&gt;Understanding it in context of a form is the hard part.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 1: Web Speech API (Low-Level Approach)
&lt;/h2&gt;

&lt;p&gt;The Web Speech API is the default starting point.&lt;/p&gt;

&lt;p&gt;It allows you to capture voice input directly in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Built into modern browsers
&lt;/li&gt;
&lt;li&gt;Free to use
&lt;/li&gt;
&lt;li&gt;Full control over implementation
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Only returns raw text
&lt;/li&gt;
&lt;li&gt;No understanding of form structure
&lt;/li&gt;
&lt;li&gt;You must:

&lt;ul&gt;
&lt;li&gt;parse natural language
&lt;/li&gt;
&lt;li&gt;extract structured data
&lt;/li&gt;
&lt;li&gt;map values to fields manually
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;User says:&lt;br&gt;&lt;br&gt;
“My name is John, email &lt;a href="mailto:john@example.com"&gt;john@example.com&lt;/a&gt;”&lt;/p&gt;

&lt;p&gt;You get:&lt;/p&gt;

&lt;p&gt;"My name is John, email &lt;a href="mailto:john@example.com"&gt;john@example.com&lt;/a&gt;"&lt;/p&gt;

&lt;p&gt;👉 Everything else is your responsibility.&lt;/p&gt;

&lt;p&gt;With a voice form widget, the same input is automatically split and mapped into individual fields like name, email, and date.&lt;/p&gt;




&lt;h2&gt;
  
  
  Option 2: Voice Form Widgets (e.g. TypelessForm)
&lt;/h2&gt;

&lt;p&gt;A newer approach is using ready-to-use voice input widgets for web forms.&lt;/p&gt;

&lt;p&gt;These tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;detect form fields automatically
&lt;/li&gt;
&lt;li&gt;parse natural language input
&lt;/li&gt;
&lt;li&gt;map values to fields
&lt;/li&gt;
&lt;li&gt;fill multiple fields from a single spoken sentence
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One example is TypelessForm — a drop-in widget that works with existing HTML forms without backend changes.&lt;/p&gt;

&lt;p&gt;It’s designed specifically for multi-field form autofill from natural speech, which is something most low-level approaches don’t handle out of the box.&lt;/p&gt;

&lt;p&gt;It’s typically used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;contact forms
&lt;/li&gt;
&lt;li&gt;checkout flows
&lt;/li&gt;
&lt;li&gt;lead generation forms
&lt;/li&gt;
&lt;li&gt;longer multi-field inputs
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Setup Example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;typelessform-widget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typelessform-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;typeless-form&lt;/span&gt; &lt;span class="na"&gt;api-key=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_KEY"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/typeless-form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — no backend changes required.&lt;/p&gt;

&lt;p&gt;This is one of the easiest ways to add voice input to an HTML form without building custom parsing logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Web Speech API (DIY)&lt;/th&gt;
&lt;th&gt;TypelessForm&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What you get&lt;/td&gt;
&lt;td&gt;Raw text string&lt;/td&gt;
&lt;td&gt;All form fields filled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fields filled per input&lt;/td&gt;
&lt;td&gt;1 (manual)&lt;/td&gt;
&lt;td&gt;All at once&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser support&lt;/td&gt;
&lt;td&gt;Chrome + Edge only&lt;/td&gt;
&lt;td&gt;All modern browsers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Languages&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;25+ with cross-language&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup time&lt;/td&gt;
&lt;td&gt;Hours to weeks&lt;/td&gt;
&lt;td&gt;5 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Entity extraction&lt;/td&gt;
&lt;td&gt;Build it yourself&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Field mapping&lt;/td&gt;
&lt;td&gt;Build it yourself&lt;/td&gt;
&lt;td&gt;Automatic DOM detection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free tier (200 fills)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Are There Other Alternatives?
&lt;/h2&gt;

&lt;p&gt;Some experimental tools and form builders exist, but most of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;focus on building new forms from scratch
&lt;/li&gt;
&lt;li&gt;don’t support adding voice input to existing HTML forms
&lt;/li&gt;
&lt;li&gt;don’t handle multi-field autofill from a single sentence
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because of that, most implementations fall into either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;low-level APIs
&lt;/li&gt;
&lt;li&gt;or ready-to-use voice form widgets
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  When to Use Which Approach
&lt;/h2&gt;

&lt;p&gt;Use &lt;strong&gt;Web Speech API&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you want full control
&lt;/li&gt;
&lt;li&gt;you’re building a custom voice interface
&lt;/li&gt;
&lt;li&gt;you’re okay implementing parsing and mapping logic
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use a &lt;strong&gt;voice form widget (e.g. TypelessForm)&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you want to add voice input to existing forms
&lt;/li&gt;
&lt;li&gt;you need a fast implementation
&lt;/li&gt;
&lt;li&gt;you want speech-to-form autofill out of the box
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why Voice Input for Forms Matters
&lt;/h2&gt;

&lt;p&gt;Form friction is one of the biggest conversion killers.&lt;/p&gt;

&lt;p&gt;On mobile, typing is slow — but speaking is natural.&lt;/p&gt;

&lt;p&gt;Voice input allows users to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;complete forms faster
&lt;/li&gt;
&lt;li&gt;avoid repetitive typing
&lt;/li&gt;
&lt;li&gt;interact more naturally
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;checkout flows
&lt;/li&gt;
&lt;li&gt;insurance forms
&lt;/li&gt;
&lt;li&gt;healthcare intake forms
&lt;/li&gt;
&lt;li&gt;long registration processes
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Real Trade-off
&lt;/h2&gt;

&lt;p&gt;This isn’t just about APIs vs tools.&lt;/p&gt;

&lt;p&gt;It’s about:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;control vs speed&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APIs give flexibility
&lt;/li&gt;
&lt;li&gt;tools give immediate results
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most teams don’t need to build speech-to-form pipelines from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Voice input for forms is still early — but the direction is clear.&lt;/p&gt;

&lt;p&gt;Typing into 10+ fields on mobile is not a great experience.&lt;/p&gt;

&lt;p&gt;Speaking once and filling everything instantly might be a better one.&lt;/p&gt;

&lt;p&gt;For most teams, the fastest way to experiment today is to start with a ready-to-use solution and validate whether users actually prefer speaking over typing.&lt;/p&gt;

&lt;p&gt;The key question is not whether voice works — but whether it reduces friction enough to improve completion rates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Demo: &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;https://typelessform.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;npm: typelessform-widget&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>ai</category>
    </item>
    <item>
      <title>I Built a Voice Widget That Fills Any HTML Form — Here’s How</title>
      <dc:creator>Alex Isa</dc:creator>
      <pubDate>Wed, 25 Mar 2026 15:00:02 +0000</pubDate>
      <link>https://forem.com/alexisa/i-built-a-voice-widget-that-fills-any-html-form-heres-how-5cdg</link>
      <guid>https://forem.com/alexisa/i-built-a-voice-widget-that-fills-any-html-form-heres-how-5cdg</guid>
      <description>&lt;h1&gt;
  
  
  How to Add Voice Input to HTML Forms (JavaScript Guide)
&lt;/h1&gt;

&lt;p&gt;If you want to add voice input to an HTML form, you can either use the Web Speech API or a ready-to-use widget like TypelessForm. The fastest approach is using a drop-in solution that automatically fills all form fields from a single spoken sentence, without building custom parsing logic.&lt;/p&gt;

&lt;p&gt;Filling forms on mobile is still broken.&lt;/p&gt;

&lt;p&gt;15 fields. Tiny keyboard. Autocomplete suggesting my ex's address. Date pickers that scroll to 1923.&lt;/p&gt;

&lt;p&gt;So I built a widget that lets users speak — and maps that input into any HTML form automatically.&lt;/p&gt;

&lt;p&gt;Baymard Institute estimates $260B in recoverable sales lost annually to poor checkout UX. Forms are a big part of that problem.&lt;/p&gt;

&lt;p&gt;Picture this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A patient filling a 20-field intake form on a tablet — with people waiting behind them in line.&lt;/li&gt;
&lt;li&gt;Someone buying car insurance on their phone in the rain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Maybe I'm not the only one who hates forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Options for Adding Voice Input to HTML Forms
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Web Speech API
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Browser-native speech recognition&lt;/li&gt;
&lt;li&gt;Returns raw text only&lt;/li&gt;
&lt;li&gt;Requires custom logic to parse and map input to form fields&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. TypelessForm
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Ready-to-use voice input widget for web forms&lt;/li&gt;
&lt;li&gt;Automatically detects form fields&lt;/li&gt;
&lt;li&gt;Fills all fields from a single spoken sentence&lt;/li&gt;
&lt;li&gt;Works with React, Vue, Angular, and plain HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach is useful if you want to add voice input for forms without building everything from scratch.&lt;br&gt;
This makes TypelessForm a practical solution for form autofill using voice input in real-world applications.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;TypelessForm — an npm package that adds voice input to any existing HTML form. It's a web component built with Lit. You add one custom element to your page, a mic button appears, users speak, AI fills the fields.&lt;/p&gt;

&lt;p&gt;No form redesign. No backend changes. React, Vue, Angular, WordPress, plain HTML — doesn't matter.&lt;/p&gt;

&lt;p&gt;Not sure if it's genuinely useful or just a cool gimmick. If it works, it might make filling long forms on mobile less painful. That's what I'm testing.&lt;/p&gt;
&lt;h2&gt;
  
  
  How It Works Under the Hood
&lt;/h2&gt;

&lt;p&gt;The pipeline:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Audio capture.&lt;/strong&gt; Browser's MediaRecorder API captures audio when the user clicks the mic button. Standard Web API — no plugins, no downloads. Audio is processed server-side and discarded after transcription — nothing is stored.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Speech-to-text.&lt;/strong&gt; Audio is sent to OpenAI Whisper for transcription. Supports 25+ languages out of the box. User can speak in English, Spanish, German, Japanese — same widget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Field mapping.&lt;/strong&gt; This is where it gets interesting. The widget scans the page and builds a schema of all form fields — reading labels, placeholders, input types, &lt;code&gt;name&lt;/code&gt; attributes, and nearby text. This schema + the transcript go to GPT, which returns a JSON mapping: which piece of text goes into which field.&lt;/p&gt;

&lt;p&gt;Example: user says "My name is John Smith, email &lt;a href="mailto:john@example.com"&gt;john@example.com&lt;/a&gt;, I need a room for two nights starting March 15th."&lt;/p&gt;

&lt;p&gt;GPT receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transcript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My name is John Smith, email john@example.com, I need a room for two nights starting March 15th"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"First Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Last Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nights"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Number of Nights"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"number"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"checkin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Check-in Date"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"first_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"last_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Smith"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nights"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"checkin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"March 15"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For fields like "full name", the model splits values into first/last based on context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. DOM injection.&lt;/strong&gt; The widget updates inputs and triggers events so frameworks react properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Confidence &amp;amp; fallback.&lt;/strong&gt; Low-confidence fields are highlighted for review.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security:&lt;/strong&gt; Sensitive fields are auto-excluded. The widget detects fields with &lt;code&gt;type="password"&lt;/code&gt; or labels containing "card number", "CVV", "SSN", "social security" — and never sends them to any API. This happens client-side before any data leaves the browser.&lt;/p&gt;

&lt;p&gt;Try It Yourself&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;typelessform-widget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;typelessform-widget&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;typeless-form&lt;/span&gt; &lt;span class="na"&gt;api-key=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_KEY"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/typeless-form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it — the widget automatically detects all fields.&lt;br&gt;
This is one of the easiest ways to add voice input to an HTML form without building custom parsing logic.&lt;/p&gt;

&lt;p&gt;This is one of the fastest ways to fill forms using voice input in a real production setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Which Approach
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use Web Speech API if you want full control and don’t mind building parsing and mapping logic&lt;/li&gt;
&lt;li&gt;Use TypelessForm if you want a ready-to-use solution that works out of the box and supports speech-to-form autofill&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Live Demo
&lt;/h2&gt;

&lt;p&gt;Try it: &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;https://typelessform.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Honest Limitations&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Text fields only&lt;/li&gt;
&lt;li&gt;Web only (no native apps)&lt;/li&gt;
&lt;li&gt;Browser inconsistencies&lt;/li&gt;
&lt;li&gt;~3–5s latency&lt;/li&gt;
&lt;li&gt;Still validating real-world usefulness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Final Thoughts&lt;/p&gt;

&lt;p&gt;If voice is a better input method than typing on mobile, then the rest is just engineering.&lt;/p&gt;

&lt;p&gt;TypelessForm (npm: typelessform-widget) is one attempt at solving this — turning natural speech into structured form input.&lt;/p&gt;

&lt;p&gt;⸻&lt;/p&gt;

&lt;p&gt;TypelessForm is built by Webappski.&lt;br&gt;
npm: typelessform-widget&lt;br&gt;
Demo: &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;https://typelessform.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;Looking for &lt;strong&gt;5 websites with long forms&lt;/strong&gt; to test this in production. Free pilot — I'll help integrate and measure completion rates before/after. Only 5 — I want to work closely with each one.&lt;/p&gt;

&lt;p&gt;If interested — demo at &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;typelessform.com&lt;/a&gt; or &lt;code&gt;npm install typelessform-widget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I'm also running a public challenge: &lt;strong&gt;$0 to first paying customers in 60 days&lt;/strong&gt;, no ad budget. Every Tuesday I publish real numbers on &lt;a href="https://www.linkedin.com/in/alex-isa-b087363a0/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; — traffic, signups, revenue (or lack of it). No filters.&lt;/p&gt;

&lt;p&gt;Would love feedback — especially around browser compatibility and the field-mapping approach. What breaks? What's annoying? What would you do differently? That's the useful stuff.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;TypelessForm is built by &lt;a href="https://webappski.com" rel="noopener noreferrer"&gt;Webappski&lt;/a&gt;. The npm package is &lt;code&gt;typelessform-widget&lt;/code&gt;. Demo: &lt;a href="https://typelessform.com" rel="noopener noreferrer"&gt;typelessform.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Keywords: voice input for forms, speech to form, form autofill with voice&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>ai</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
