The Setup

We're building a cancer education business Finder, a chat-first app that matches patients with cancer treatment facilities.

When a patient goes through the chat, we collect their name, email, and phone.

So when they're ready to book — and a facility has a HubSpot meeting scheduler embedded right in the card — the obvious move is to pre-fill the form.

Don't make them type their name again. We already have it.

The Code I Wrote

I put a buildHubspotUrl() function in src/lib/hubspot.ts.

Validate the URL, split the full name, append query params. Dead simple:

if (firstName) url.searchParams.set("firstName", firstName);
if (lastName)  url.searchParams.set("lastName", lastName);
if (lead.email) url.searchParams.set("email", lead.email);
if (lead.phone) url.searchParams.set("phone", lead.phone);

Looked right to me. It's TypeScript — camelCase is what you do.

The Wall

The iframe loaded.

The form appeared.

Every field was completely blank.

No errors. No warnings. HubSpot just… ignored my params.

I checked URL encoding. I double-checked the scheme validation. I read docs on how HubSpot embeds work.

And then — eventually, embarrassingly — I looked at an actual HubSpot prefill example in their docs.

?firstname=Jane&lastname=Doe

Not firstName. Not lastName.

firstname. lastname. All lowercase, single word, no camel.

The Fix

Two characters changed per param name. That's it.

if (firstName) url.searchParams.set("firstname", firstName);
if (lastName)  url.searchParams.set("lastname", lastName);

Pre-fill worked instantly.

Why This Matters

My instinct was to name params the way I name things in TypeScript.

That's the trap.

Third-party form APIs have their own field namespace — and it's theirs, not yours.

HubSpot uses lowercase single-word contact properties: firstname, lastname, email, mobilephone.

Fillout (my other go-to form tool) accepts camelCase URL params like ?matterId=xxx. Web3Forms uses snake_case hidden fields: access_key, from_name.

None of them agree. None of them have to.

The rule isn't "use lowercase." The rule is: open their docs before you open your editor, and copy their exact param names character for character.

URL params are silently ignored when they don't match. No 400. No console error. Just a blank form and a confused patient staring at a text field they already filled out once.

That silence is the real bug. Two minutes reading HubSpot's prefill docs would have saved me a round of debugging.

Check the provider's field names first. Every time.

P.S. The fix is a one-liner per field — but the lesson is worth more than the code. When a third-party integration silently ignores your data, the first question is always: "am I using their names, or mine?"