DEV Community

Cover image for A Guide to Creating a Serverless Function for Fetching External Data on Hubspot
Mario Dias
Mario Dias

Posted on

A Guide to Creating a Serverless Function for Fetching External Data on Hubspot

HubSpot offers a powerful platform for creating user interfaces (UI) and serverless functions using React, allowing users to develop highly customizable pages and forms directly within the CRM itself.

This approach enables the creation of tailor-made solutions without the need to configure additional servers or infrastructure. Using React provides a smooth and interactive experience, making it easy to customize elements efficiently.

This integration offers greater flexibility and control, allowing marketing, sales, and customer service professionals to create pages that meet their exact needs, all within the HubSpot environment.

For this project, the prerequisites are having a HubSpot developer account and a solid understanding of React, JavaScript, and serverless functions. These skills are essential for building and customizing pages and forms within the HubSpot CRM.

To get started, HubSpot provides a detailed quickstart guide that will walk you through the process of setting up your development environment and building your first private app. You can access the guide here.


Serverless functions are an efficient way to handle lightweight backend logic without managing a full server infrastructure. In this guide, we'll create a serverless function that fetches commercial group information based on a CNPJ (Cadastro Nacional da Pessoa Jurídica, Brazil's company registration number).

Step 1: Define the Serverless Function in serverless.json file in your project

To integrate the function into your application, you first need to register it in the serverless.json file. This file informs your system about available serverless functions and where to find their implementations. This file is on app.functions folder.

Add the following configuration to your serverless.json:

{
  "handleGetCommercialGroupFunc": {
    "file": "get-commercial-group.js",
    "secrets": []
  }
}
Enter fullscreen mode Exit fullscreen mode

This entry maps the function name handleGetCommercialGroupFunc to the file get-commercial-group.js, which we will create next.


Step 2: Create the Serverless Function

In app.functions folder, create a file named get-commercial-group.js and implement the following logic:

exports.main = async (context = {}) => {
  const { cnpj } = context.parameters;

  if (!cnpj) {
    return {
      statusCode: 400,
      body: { error: "CNPJ is required." },
    };
  }

  try {
    // Replace with your actual API URL
    const apiUrl = `https://YOUR-API-ENDPOINT?cnpj=${encodeURIComponent(cnpj)}`;

    // Make the API request
    const apiResponse = await fetch(apiUrl, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    });

    if (!apiResponse.ok) {
      throw new Error(`API Error: ${apiResponse.status} - ${apiResponse.statusText}`);
    }

    const data = await apiResponse.json();

    return {
      statusCode: 200,
      body: data,
    };
  } catch (error) {
    console.error("Serverless function error:", error);

    return {
      statusCode: 500,
      body: { error: "Failed to fetch data.", details: error.message },
    };
  }
};
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • Input Validation: The function checks if the cnpj parameter is provided. If not, it returns a 400 Bad Request error.
  • API Call: It makes a GET request to the specified API using the provided CNPJ.
  • Error Handling: The function handles errors gracefully, returning meaningful error messages for debugging.
  • Response: On success, it returns the API response as-is, allowing the frontend to handle it.

Step 3: Frontend Integration

We create a simple interface within HubSpot using React that allows the user to provide a CNPJ and retrieve information related to the business group associated with that key.

The code below uses the @hubspot/ui-extensions library to build the interface, including input fields and a button that triggers a serverless function. The serverless function is called with the CNPJ as a parameter, and the response is displayed in the interface.

import React, { useState } from "react";
import {
  Divider,
  Button,
  Text,
  Input,
  Flex,
  hubspot,
} from "@hubspot/ui-extensions";

hubspot.extend(({ context, runServerlessFunction, actions }) => (
  <Extension
    context={context}
    runServerless={runServerlessFunction}
    sendAlert={actions.addAlert}
    openIframe={actions.openIframeModal}
  />
));

// Define the Extension component, taking in runServerless, context, & sendAlert as props
const Extension = ({ context, runServerless, sendAlert, openIframe }) => {

  const [cnpj, setCnpj] = useState("");
  const [commercialGroup, setCommercialGroup] = useState("");

  const handleGetCommercialGroup = async () => {
    try {
      console.log('Calling handleGetCommercialGroupFunc with CNPJ:', cnpj);

      const { response } = await runServerless({ name: "handleGetCommercialGroupFunc", parameters: { cnpj } });

      console.log('Serverless function response:', response);
      setCommercialGroup(JSON.stringify(response));

      sendAlert({ message: JSON.stringify(response, null, 2) });

    } catch (error) {
      console.error('Error searching for business group:', error);
      sendAlert({ message: error.message });
    }
  };

  return (
    <>
      <Text>
        <Text format={{ fontWeight: "bold" }}>
          My Custom Form on HubSpot
        </Text>
      </Text>
      <Flex direction="row" align="end" gap="small">
        <Input name="cnpj" label="CNPJ" onInput={(cnpj) => setCnpj(cnpj)} />
        <Button type="submit" onClick={handleGetCommercialGroup}>
          Get Commercial Group
        </Button>
      </Flex>
      <Divider />
      <Flex direction="row" align="end" gap="small">
        <Input name="commercial_group" label="Commercial Group" value={commercialGroup} />
      </Flex>
      <Divider />
    </>
  );
};
));
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • State Management: The cnpj and commercialGroup values are stored in the component's state using useState. The cnpj input is updated when the user types into the input field, while the commercialGroup value is updated when the serverless function response is received.
  • Calling the Serverless Function: The runServerless function is invoked when the user clicks the "Get Commercial Group" button. It sends the CNPJ as a parameter to the serverless function (handleGetCommercialGroupFunc).
  • Response Handling: Once the serverless function responds, the component captures the response and updates the commercialGroup state with the response data. The result is displayed in the commercialGroup input field. Additionally, if there’s an error, it’s captured and shown as an alert using the sendAlert function.

Step 4: Testing the Function

  • Run the Frontend: Launch your application and enter a CNPJ in the input field.
  • Check Logs: Monitor console logs in both the frontend and serverless function to debug issues.
  • Validate API Responses: Ensure the API returns the expected data format:
   {
     "name": "Company Name",
     "value": 12345.67,
     "type": "Business Type"
   }
Enter fullscreen mode Exit fullscreen mode

Conclusion

This serverless function demonstrates how to fetch data on Hubspot from an external API using a CNPJ as input. By following the steps above, you can integrate similar serverless functionality into your projects, reducing backend complexity and enhancing scalability. For further improvements, consider adding caching mechanisms or input sanitization to make the function more robust.

Leveraging this approach within the HubSpot CRM provides users with an extremely high level of customization. Not only can you create dynamic user interfaces directly within the CRM pages, but you can also dynamically manipulate values and data via APIs, giving you complete flexibility to tailor the CRM experience to your specific needs and workflows. This integration streamlines your processes, offering greater control and efficiency across your CRM operations.

Photo by Campaign Creators on Unsplash

Top comments (0)