Sometimes you are just confronted with a question and you think “This should be there” but it’s not. This was the case when someone asked me if you could send leads generated from the Azure Marketplace to HubSpot. Apparently Azure Marketplace cannot send Leads directly to HubSpot. If we look at how HubSpot is built that makes perfect sense.. Azure Functions to the rescue!

Mind you, this can also be done with Logic Apps and Power Apps but I found that I wanted more customization and control. This is when Azure Functions would be preferred weapon of choice.

Long story short.. Code here.

Requirements

For this to work we need a couple of things:

If you’re using Visual Studio Code (Why aren’t you?!?) you can use the examples from the Microsoft Docs to get started and set up your Function App (Link)

Once you have deployed your function app, make sure to add the app setting that contains the HubSpot API Key (key: hubspotAPIKey, value: YourAPIKey).

If you created the App beforehand, you can add the setting whenever you want. If you are using Visual Studio Code. Deploy the whole thing and add the app setting before you start testing.

The code

Before we start testing, let’s take a look a the code (apart from the Azure Function standard things you need). The HubSpot APIs aren’t great (well the documentation isn’t) but they work.

First we need to get the APIKey. We’re grabbing that from the App Settings because we’re using ConfigurationBuilder (using Microsoft.Extensions.Configuration;). We then create a string for the baseURI and add the hubspotAPIkey we retrieved from the App settings. Could do this in two lines but I prefer this as it is more readable.

// Hubspot API information
string hubspotAPIKey = config["hubspotAPIKEY"];
string baseURI = "https://api.hubapi.com/contacts/v1/contact/?hapikey=";
string URI = baseURI + hubspotAPIKey;

Whenever someone uses your Azure Marketplace item, a lead is generated. That is processed according to whatever you configured (HTTPS Endpoint, CRM, Table storage, etc). In this example we configured an HTTPS endpoint which is our Azure Function. That means the lead will be sent to the function for processing.

What we’re doing here is reading the requestBody and then deserialize it to an object using the AzureMarketPlaceLead class. We now have something to work with 🙂

// Process leads from the marketplace
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
Lead deserializedMarketplaceLead = JsonConvert.DeserializeObject<Lead>(requestBody);

Next we need to determine which properties go to HubSpot to create a contact. And that is where a lot of customization comes in. The properties need to exist within HubSpot. You can add properties or use existing ones to store the information you need. In this example I used some hardcoded values which you can modify to your liking. I tried to match what was available by default but for the Offer ID I had to use the default message field. (so you know what offer they clicked on and what the lead is about).

If you need the actual property names that your HubSpot will accept, please check https://api.hubapi.com/properties/v1/contacts/properties?hapikey=<hubspotAPIKey>

We then serialize this into Json using the HubSpotContact class.

var details = new HubSpotContactPoperties();
        details.properties = new List<Property>
        {
            new Property { property = "firstname", value = deserializedMarketplaceLead.userDetails.firstName },
            new Property { property = "lastName", value = deserializedMarketplaceLead.userDetails.lastName },
            new Property { property = "email", value = deserializedMarketplaceLead.userDetails.email },
            new Property { property = "website", value = "NotProvidedFromAzureMarketPlace" },
            new Property { property = "company", value = deserializedMarketplaceLead.userDetails.company },
            new Property { property = "phone", value = deserializedMarketplaceLead.userDetails.phone },
            new Property { property = "address", value = "NotProvidedFromAzureMarketPlace"},
            new Property { property = "city", value = "NotProvidedFromAzureMarketPlace" },
            new Property { property = "state", value = "NotProvidedFromAzureMarketPlace" },
            new Property { property = "zip", value = "NotProvidedFromAzureMarketPlace" },
            // You could use deserializedMarketplaceLead.leadSource here but it needs to exist in Hubspot!
            new Property { property = "lead_source", value = "Microsoft.com Referral"},
            new Property { property = "message", value = "Offer Title: " + deserializedMarketplaceLead.offerTitle }
        };
// Serialize details to jsonBody
string jsonBody = JsonConvert.SerializeObject(details);

Now we can use an HTTP Client to send a POST request to the HubSpot contacts API to create a new contact:

// Write contact to hubspot
static async Task<string> WriteLeadHubSpot(string URI, string jsonBody)
{
    HttpClient httpClient = HTTPClient();
    StringContent postBody = new StringContent(jsonBody, Encoding.UTF8, "application/json");
    HttpResponseMessage response = await httpClient.PostAsync(URI, postBody);
    response.EnsureSuccessStatusCode();
    string responseBody = await response.Content.ReadAsStringAsync();
    return responseBody;
}

Once again, the complete working code (function) can be downloaded here.

Time to see this in action!

Bring the action

We’re first going to Partner Center to check out marketplace item (direct link).  Go to “Offer Setup” and under “Customer Leads” configure the HTTPS endpoint for your leads. Be aware that you include the Function key. Next click on “Validate” to trigger your function.

If everything goes well you should see a new contact in HubSpot within a couple of seconds.

Clicking on the details and inspecting the properties also shows that data has been send successfully and the values are there.

Once again, if you want to use additional properties (and perhaps add information from other sources): HubSpot supports many, many properties that you can use. As long as the property exists in HubSpot you can pass it along with any value you want, or with a value that comes from the Azure Marketplace. The properties need to match exactly. You can query the endpoint: https://api.hubapi.com/properties/v1/contacts/properties?hapikey=hubspotAPIKey to verify the existence of a property.

Wrap-up

This function still has a lot of stuff that can be added. Think of OAuth (which HubSpot supports), you might not always want to use the APIKey. If you are going to use different endpoints on api.hubapi.com, you might even need OAuth as not everything is supporting just the APIKey. Also, if you’re getting a lot of hits on your marketplace item, some error handling or additional storage (table storage perhaps) would come in handy.

This example uses the contacts API to create a new contact based on the leads generated from the Azure Marketplace. If you’re using custom forms for registering leads in HubSpot, you can call those through the HubSpot APIs as well. It really depends on your workflows in HubSpot what happens after creating a new contact.

Hope this helps your Azure Marketplace lead management! If you have feedback or questions, let me know!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.