The challenge you’re having is that HubSpot’s native attribution only works when someone completes an actual HubSpot form. When leads come in via API (like from your app signup), HubSpot has no way to connect that new contact to their previous website activity, so it defaults to “Offline Sources.”
The best way to solve this is to capture the attribution data when visitors first land on your website, store it in your database when the user signs up, and then include it in the API payload you send to HubSpot to create a new contact.
Tools like Attributer can help with this. You put their code on your site, and when a visitor lands on your site, it stores the UTM parameters, referrer data, and other attribution information in a first-party cookie. Then, when the user signs up in your app, you can pull that data from the cookie using JavaScript and store it in your database (usually on the users or accounts table). Finally, you send it along with the contact creation API call to HubSpot (and you can also send it to other tools as well, like billing platforms such as Stripe, product analytics tools like Amplitude, etc).
With this approach, even though the signup didn’t happen through a HubSpot form, you’re still sending HubSpot the original source information (Paid Search, Organic Search, Paid Social, etc.) plus campaign details, landing page, and other context.
You could also write custom JavaScript to handle the cookie storage and retrieval yourself, but that requires ongoing maintenance as browsers update and your site structure evolves.
The key is capturing the attribution data early in the visitor journey and then making sure it gets passed through when the API creates the contact in HubSpot.
P.S If this all sounds technical, it’s not that hard. Your developers could probably get this all set up in about an hour.
P.P.S: I used an AI assistant to help structure this response because I’m not great at writing, but the advice comes from my experience and I’ve reviewed it before posting.