I don't just talk about automation. I build things that actually run.

Three kinds of proof: workflows running in production with real conversion data, twelve builds done in twelve days, and full apps that are live today. Everything is there to download, import, or click through. You don't have to take my word for it.

Daniel Sfita working on automations, headphones on
Offline conversions, closed-loopBuilt in n8nHubSpotMicrosoft Advertising

Every pulse is a HubSpot lifecycle change. Gates drop anything without an ad click ID or already uploaded; closed-won deals carry revenue into Microsoft Ads so bidding optimizes toward customers, not clicks.

Waiting for the first event…
conversion event revenue upload filtered out ⤺ dashed = flag written back
How it works

The problem it solves. When someone clicks a Microsoft (Bing) ad, Microsoft can see the click, but it loses track of what happens after that. The person might fill out a form, become a lead in HubSpot, turn into an SQL a few days later, and eventually become a customer. Microsoft sees almost none of that.

That means its bidding algorithm is learning from clicks and form submissions, rather than from the people who actually become customers.

Offline conversion tracking fixes that. Every ad click comes with a unique msclkid. I store that ID on the HubSpot contact, and when the contact later becomes an MQL, SQL, or closed-won customer, I send that information back to Microsoft. For closed-won deals, I can even send the deal value.

So instead of learning, "this type of person fills out forms," Microsoft can start learning, "this type of person actually becomes a customer."

How the direct API version works. HubSpot sends a webhook to n8n whenever something relevant changes on a contact or deal. From there, the workflow checks what happened and decides whether it needs to send a new conversion to Microsoft.

For example, if a contact becomes an MQL or SQL, it first checks whether they actually came from a Microsoft ad by looking for the msclkid. Organic leads are ignored. It also checks whether that conversion has already been uploaded, so the same person doesn't get counted twice.

If everything looks good, n8n sends the conversion directly to Microsoft's Offline Conversions API. For closed-won deals, it also sends the deal value in EUR.

Once Microsoft has received it, the workflow updates a property in HubSpot to basically say: "We've already sent this one." That small step is what stops duplicate conversions if HubSpot triggers the workflow again later.

Same workflow, second implementation — via Google Sheets

Same pipeline, spreadsheet editionBuilt in n8nGoogle Sheets

Rows land in a sheet Microsoft Ads imports on schedule — every conversion visible and auditable. The amber lane is the part tutorials skip: a weekly cron keeps only the last 14 days so the sheet never re-uploads stale conversions.

Waiting for the first event…
conversion event row appended weekly cleanup filtered out
Why I built a second version

Calling Microsoft’s API directly is probably the cleaner setup. But there’s another option: Microsoft Ads can also import offline conversions from a Google Sheet on a schedule.

It’s a bit less elegant, but I actually like it for a few reasons. You can open the sheet and see exactly what’s being sent to Microsoft, it’s easier for someone else to troubleshoot, and you don’t have to rely as much on API authentication working perfectly.

So instead of sending conversions straight to Microsoft, this version writes them into a Google Sheet. Microsoft then imports that sheet automatically.

The part I like most is actually the boring bit.

Once a week, the workflow checks the sheet, keeps the last 14 days of conversion data, removes everything older, and writes the recent rows back.

It sounds like a small detail, but it matters. Microsoft keeps coming back to the same sheet to import conversions. If you never clean it up, you eventually end up with months or years of old data sitting there and being checked again and again.

That’s the kind of thing you probably wouldn’t bother building into a quick demo. But if the automation is supposed to keep running for months without anyone thinking about it, it suddenly becomes important.

Let's talk

Interested in working together, collaborating, or exploring an idea? Tell me a bit about your project and I'll get back to you as soon as I can. Or use the floating button bottom-right to grab a 15-min slot directly.

Whether you’re a startup looking for your first proper marketing engine, or an established brand exploring how AI can support your growth, I’d love to hear from you.

Share a few details about your goals, timelines, and current challenges. I’ll respond shortly on how (and if) I can help.

Location: Copenhagen, Denmark
LinkedIn: Connect with me
GitHub: babaliba-oss
Book a call: Grab a 15-min slot