> ## Documentation Index
> Fetch the complete documentation index at: https://br.developers.hubspot.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Introdução às funções sem servidor

> Crie sua primeira função sem servidor no HubSpot CMS e obtenha uma resposta.

'Crie sua primeira função sem servidor no HubSpot CMS e obtenha uma resposta.';

<ProductTier tiers={['cms-enterprise']} />

As funções sem servidor fornecem uma maneira de executar o JavaScript através da HubSpot no lado do servidor, impedindo que ele seja exposto ao cliente. Isso pode ser especialmente importante para fazer solicitações de API que contêm informações confidenciais, como um Chave de API ou outras credenciais. Quando a função é invocada, a HubSpot executa a função em seu back-end, o que também significa que você não precisa fornecer seus próprios servidores back-end para fazer solicitações para seu site CMS. As funções sem servidor da HubSpot usam o tempo de execução do [NodeJS](https://nodejs.org/en/about/).

Neste guia, você criará uma função simples sem servidor que obtém um menção de um serviço de terceiros e exibirá esse menção em um página do site. Para construir e implantar a função sem servidor em sua conta, você usará um projeto de desenvolvedor HubSpot.

<Alert type="warning" titleText="Observação:">
  Embora o método documentado anteriormente de carregar funções sem servidor ao
  gerenciador de design ainda seja suportado, é recomendável usar projetos de
  desenvolvedor visto que incluem um aplicativo privado para facilitar a
  autenticação e, ao mesmo tempo, permitir dependências de terceiros. O conteúdo
  deste guia foi atualizado para usar o método mais recente. Você pode encontrar
  informações de referência para funções sem servidor à base de gerenciador de
  design na [seção de
  referência](/cms/reference/serverless-functions/serverless-functions-in-projects).
</Alert>

Para uma visão geral de alto nível das funções sem servidor, consulte a [visão geral das funções sem servidor](https://developers.hubspot.com/docs). Você também pode verificar o [Canal do YouTube dos desenvolvedores do HubSpot](https://www.youtube.com/watch?v=N0arXQOyfXo) para um passo a passo da utilização de funções sem servidor em um projeto CMS.

## Pré-requisitos

Antes de iniciar este tutorial, você precisará de:

* Uma conta \_ **Content Hub** Enterprise\_, ou uma [conta de ambiente de testes de desenvolvedor do CMS](https://app.hubspot.com/signup-hubspot/cms-developers).
* O [CLI da HubSpot](/developer-tooling/local-development/hubspot-cli/reference#install-the-cli) (recomenda-se a versão mais recente), que precisará ser instalada e autenticada com a conta que você está usando. Para verificar quais contas são autenticadas, você pode executar `hs accounts list`. Saiba mais sobre [introdução ao desenvolvimento local](/developer-tooling/local-development/hubspot-cli/install-the-cli).

## 1. Criar um projeto localmente

Comece criando um projeto localmente para que você possa compilá-lo e implantá-lo em sua conta.

* No terminal, navegue para o diretório onde você armazenará seu projeto usando o comando `cd`.

```shell theme={null}
cd Documents/Dev/serverless-function-project
```

* Execute `hs project create` para criar um novo projeto.

```shell theme={null}
hs project create
```

* Siga os prompts de terminal para criar seu projeto. Para o modelo, selecione **Criar um projeto vazio (sem modelo)**.

![Opção de prompt de terminal para a criação de um projeto vazio sem modelo](https://br.hubspot.com/hubfs/Knowledge_Base_2023-24-25/terminal-select-empty-project.png)

* Navegue até o novo diretório do projeto usando o comando `cd`. Por exemplo, se você nomeou seu projeto *meu novo projeto*:

```shell theme={null}
cd my-new-project
```

## 2. Adicione uma função sem servidor ao projeto

Depois que o projeto tiver sido criado, abra-o no editor de sua preferência, como [Código VS](https://developers.hubspot.com/docs). A HubSpot terá criado automaticamente um diretório de projeto com um diretório vazio `src` e um arquivo de configuração `hsproject.json`. Para adicionar uma função sem servidor ao projeto, crie um diretório `app` dentro do diretório `src` e adicione os seguintes diretórios e arquivos dentro dele:

* `app/app.json`: o arquivo de configuração do aplicativo.
* `app/app.functions`: o diretório da função sem servidor. Você pode usar qualquer nome desejado, desde que termine em `.functions`.
* `app/app.functions/function.js`: o código JavaScript que será executado quando a função for chamada.
* `app/app.functions/serverless.json`: o arquivo de configuração da função sem servidor.
* `app/app.functions/package.json`: inclui as dependências necessárias.

![Estrutura do projeto após adicionar os arquivos e pastas acima ao diretório do projeto](https://br.hubspot.com/hubfs/Knowledge_Base_2023-24-25/project-serverless-functions-structure.png)

* Copie o código de exemplo abaixo para o seus respectivos arquivos locais `app.json`, `function.js`, `serverless.json` e `package.json`. Em cada bloco de código `.json`, você também encontrará uma tabela contendo definições de campo.

<Tabs defaultSelected="0">
  <Tab tabId="0" title="app.json">
    ```json theme={null}
    {
      "name": "Serverless function app",
      "description": "This app runs a serverless function to fetch a quote using the Zen Quotes API.",
      "scopes": ["crm.objects.contacts.read", "crm.objects.contacts.write"],
      "uid": "serverless-function-app",
      "public": false
    }
    ```

    | Campo         | Tipo   | Descrição                                                                                                                                                                                                                                                                                                                                            |
    | ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `name`        | String | O nome do aplicativo, que será exibido na interface do usuário da HubSpot.                                                                                                                                                                                                                                                                           |
    | `description` | String | A descrição do aplicativo, que será exibida na interface do usuário da HubSpot.                                                                                                                                                                                                                                                                      |
    | `scopes`      | Matriz | Os escopos aos quais o aplicativo tem acesso para solicitações de autenticação com o token de acesso do aplicativo privado. Os dois escopos acima são os escopos mínimos necessários. Nenhum escopo adicional foi adicionado a este tutorial, pois você não precisará usar o token de acesso de aplicativo privado para a solicitação que você fará. |
    | `uid`         | String | O identificador exclusivo do aplicativo. Isso pode ser qualquer string, mas deve identificar significativamente o aplicativo. A HubSpot identificará o aplicativo por esta ID para que você possa alterar o `name` do app localmente ou na HubSpot sem remover dados históricos ou de estado, como logs.                                             |
    | `public`      | String | Definir como `false` para aplicativos privados.                                                                                                                                                                                                                                                                                                      |
  </Tab>

  <Tab tabId="1" title="function.js">
    Esta função buscará um orçamento aleatório do [API de Cotações Zen](https://zenquotes.io/).

    ```js theme={null}
    const axios = require("axios");

    exports.main = async context => {
      try {
        // Make GET request to the ZenQuotes API
        const response = await axios.get("https://zenquotes.io/api/random");

        // Extract the quote data (first item in the array)
        const quoteData = response.data[0];

        // Log the quote and author to console
        console.log(`"${quoteData.q}" — ${quoteData.a}`);

        // Return a properly formatted response with status code and body
        return {
          statusCode: 200,
          body: quoteData,
          headers: {
            "Content-Type": "application/json",
          },
        };
      } catch (error) {
        // Handle any errors that occur during the request
        console.error("Error fetching quote:", error.message);

        // Return an error response
        return {
          statusCode: 500,
          body: { error: "Failed to fetch quote" },
          headers: {
            "Content-Type": "application/json",
          },
        };
      }
    };
    ```
  </Tab>

  <Tab tabId="2" title="serverless.json">
    ```js theme={null}
    {
      "appFunctions": {
         "quote-function": {
          "file": "function.js",
          "secrets": [],
          "endpoint": {
            "path": "fetch-quote",
            "method": ["GET"]
           }
        }
      }
    }

    ```

    | Campo            | Tipo   | Descrição                                                                                                                                                                                                                              |
    | ---------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `quote-function` | Objeto | Um objeto contendo os detalhes de configuração da função sem servidor. Este objeto pode ter qualquer nome, mas ele deve corresponder ao nome de campo associado que você mencionou na `appFunctions` no seu arquivo `serverless.json`. |
    | `file`           | String | O nome do arquivo JavaScript que contém o código de função sem servidor a ser executado.                                                                                                                                               |
    | `secrets`        | Matriz | Uma matriz que contém nomes de segredos que a função usará para autenticar solicitações. Para este tutorial, nenhum segredo é necessário.                                                                                              |
    | `endpoint`       | Objeto | Um objeto contendo detalhes sobre o endpoint que você pode pressionar para chamar a função. O campo `path` define o último valor no caminho do endpoint `/hs/serverless/<path>`, enquanto o `method` define o método de solicitação.   |
  </Tab>

  <Tab tabId="3" title="package.json">
    ```json theme={null}
    {
      "name": "example-serverless-function",
      "version": "0.1.0",
      "author": "HubSpot",
      "license": "MIT",
      "dependencies": {
        "@hubspot/api-client": "^7.0.1",
        "axios": "^0.27.2"
      }
    }
    ```

    | Campo          | Tipo   | Descrição                                             |
    | -------------- | ------ | ----------------------------------------------------- |
    | `dependencies` | Objeto | As dependências incluídas para a função sem servidor. |
  </Tab>
</Tabs>

* Depois de adicionar o código acima, salve suas alterações.

## 3. Carregar o projeto na HubSpot

Com as alterações salvas, você pode carregar o projeto na HubSpot para compilar e implantar o aplicativo e a função sem servidor.

* No terminal, execute `hs project upload`.

```shell theme={null}
hs project upload
```

* Confirme se deseja criar o projeto na conta. Você não precisará confirmar novamente isso após a criação inicial. O terminal exibirá o status atual das etapas de compilação e implantação à medida que avançarem.
* Quando o upload for concluído, execute `hs project open` para exibir o projeto na HubSpot.

```shell theme={null}
hs project open
```

Na HubSpot, você pode exibir os detalhes do projeto, criar e implantar logs, logs de funções sem servidor, gerenciar o projeto e o aplicativo e muito mais. Saiba mais sobre como [gerenciar projetos na HubSpot](https://developers.hubspot.com/docs#view-the-project-in-hubspot).

## 4. Testar a função

Com a função sem servidor implantada, você pode chamá-la acessando seu URL público. As funções sem servidor construídas com projetos de desenvolvedor têm a seguinte estrutura de URL pública: `https://<domain>/hs/serverless/<endpoint-path-from-config>`.

* `<domain>`: você pode usar qualquer domínio conectado à conta. Por exemplo, se website.com e subdomain.brand.com estiverem conectados à conta, você poderá chamar a função usando `https://website.com/hs/serverless/<path>` ou `https://subdomain.brand.com/hs/serverless/<path>`.
* `<endpoint-path-from-config>`: o valor no campo `path` em `serverless.json`.

Com base no código de exemplo fornecido neste tutorial, o URL público para chamar a função será: `https://<domain>/hs/serverless/fetch-quote`.

<Alert type="info">
  No URL para chamar a função, o caminho do endpoint é global em vez de com
  escopo para o aplicativo ou projeto. Se houver caminhos de endpoint idênticos
  entre vários aplicativos ou projetos, a função de endpoint implantada mais
  recentemente tem precedência.
</Alert>

Para exibir a saída da função, navegue até esse URL no navegador, substituindo o domínio por um dos domínios hospedados na HubSpot. Se você não conectou um domínio personalizado, poderá usar um dos domínios padrão fornecidos pela HubSpot: `<hubId>.hs-sites.com` (por exemplo, `123456.hs-sites.com`). Seu navegador deve exibir os dados retornados pela API Zen Quotes.

![Navegador exibindo os dados retornados pela API Zen Quotes](https://br.hubspot.com/hubfs/Knowledge_Base_2023-24-25/zen-quotes-api-return.png)

## 5. Invocar a função de um página do site

Agora que você criou a função sem servidor e confirmou que ela retorna dados, implemente-a em uma página para ver os dados retornados em um contexto mais realista. Para este tutorial, você criará um modelo de página contendo alguns JavaScript e HTML personalizados para executar a função e exibir os dados de resposta.

Primeiro, crie um novo modelo de página:

* No ambiente local, crie um novo diretório para conter o modelo de página. Para os propósitos deste tutorial, crie este diretório fora do diretório do projeto criado por `hs project create`.

* No terminal, navegue até esse diretório usando o comando `cd`.

```shell theme={null}
cd Documents/Dev/serverless-page
```

* Execute `hs create template "serverless-template"` para criar um novo modelo chamado `serverless-template`.

```shell theme={null}
hs create template "serverless-template"
```

* Selecione o tipo de modelo da **página**.
* Abra o arquivo de modelo de página recém-criado no editor e substitua o código de formatação pelo código abaixo. Certifique-se de substituir `<domain>` no URL do endpoint da função (`fetch('http://<domain>/hs/serverless/fetch-quote')`) com um domínio conectado à sua conta HubSpot.

```html theme={null}
<!--
    templateType: page
    label: Serverless function example template
    isAvailableForNewContent: true
-->
<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>{{ content.html_title }}</title>
    <meta name="description" content="{{ content.meta_description }}" />
    {{ standard_header_includes }}
  </head>
  <body>
    {% module "page_template_logo" path="@hubspot/logo" label="Logo" %}
    <!-- Button to fetch quote via serverless function -->
    <div class="serverless-container">
      <h2>Get quote</h2>
      <p class="subtitle">Click the button to fetch and display a quote.</p>
      <button id="data-button" type="button">Get quote!</button>
      <div id="data-container">
        <p class="data"></p>
      </div>
    </div>
    <!-- End button section -->

    {{ standard_footer_includes }}

    <!-- JavaScript that invokes the serverless function
     and adds returned data into the "data" text element -->
    <script>
      const dataButton = document.getElementById("data-button");
      const dataContainer = document.getElementById("data-container");

      dataButton.addEventListener("click", function (e) {
        console.log("Button clicked!");

        // Show loading state
        dataContainer.innerText = "Loading...";
        // Replace <domain> with your own domain
        fetch("http://<domain>/hs/serverless/fetch-quote")
          .then(response => {
            if (!response.ok) {
              throw new Error(`HTTP error! Status: ${response.status}`);
            }
            // Parse the JSON response
            return response.json();
          })

          .then(data => {
            console.log("Raw data received:", data);

            // Clear container
            dataContainer.innerText = "";

            // Create the paragraph element
            const newDataElement = document.createElement("p");
            newDataElement.innerText = `"${data.q}" — ${data.a}`;
            dataContainer.appendChild(newDataElement);
          });
      });
    </script>
  </body>
</html>
```

* Salve o arquivo e execute `hs upload` para carregá-lo na HubSpot. Siga os prompts de terminal para selecionar o caminho local de origem e destino. Para este tutorial, você pode apenas pressionar **Inserir** para cada prompt para usar os caminhos padrão.

Em seguida, crie uma nova página a partir do modelo na HubSpot.

* Navegue até o página do site da sua conta HubSpot executando o `hs open website-pages`.

```shell theme={null}
hs open website-pages
```

<Alert type="info">
  Veja a lista completa de atalhos abertos disponíveis executando `hs
      open--list`.
</Alert>

* No navegador, clique em **Criar** no canto superior direito para criar uma nova página.
* Na caixa de diálogo, selecione um **domínio** para usar, depois atribua um **Nome da página**. O domínio da página precisará corresponder ao domínio que você está usando para chamar a função sem servidor para evitar erros de origem cruzada (CORS). Você pode selecionar esse domínio no menu suspenso ou atualizar o URL do endpointno código de modelo de página (`fetch('http://<domain>/hs/serverless/fetch-quote')`) para usar o domínio selecionado nesta etapa.
* Clique em **Criar página**.
* Na tela de seleção de modelo, procure o novo modelo. Você pode usar o rótulo ou o nome do arquivo para pesquisar o modelo (por exemplo, "Página de exemplo da função sem servidor"). O modelo aparecerá em *Outros modelos*, pois não faz parte de um tema.

![Outra seção de modelos mostrando o modelo de página recém-criado](https://br.hubspot.com/hubfs/Knowledge_Base_2023-24-25/select-new-template.png)

* Clique em **Selecionar modelo**.
* No editor de página, clique em **Visualizar** na parte superior direita.

![Botão de visualização do editor de página](https://br.hubspot.com/hubfs/page-preview.png)

* Clique em **Abrir em uma nova guia**.

Na nova guia, você agora deve ser capaz de clicar no botão para buscar e exibir cotações.

![Demonstração do botão de exemplo que obtém e exibe cotações da API Zen Quotes](https://br.hubspot.com/hubfs/Knowledge_Base_2023-24-25/quote-button-demonstration.gif)

## Próximas etapas

Agora que você criou e implementou uma função sem servidor que interage com uma API de terceiros, há algumas maneiras de continuar aumentando o uso da função sem servidor, como:

* [Incluir autenticação em uma solicitação](/cms/reference/serverless-functions/serverless-functions-in-projects#authentication) para fazer chamadas para APIs HubSpot ou outras APIs autenticadas de terceiros.
* Implementar o botão e o código JavaScript em um módulo em vez de inseri-los no modelo de página. Isso lhe daria uma opção mais portátil, permitindo que a função fosse chamada de qualquer página à qual o módulo fosse adicionado. Para fazer isso, crie um módulo e adicione o HTML ao `module.html` e o JavaScript no arquivo `module.js`.

<Tabs defaultSelected="0">
  <Tab tabId="0" title="module.html">
    ```html theme={null}
    <div class="serverless-container">
      <h2>Get quote</h2>
      <p class="subtitle">Click the button to fetch and display a quote.</p>
      <button id="data-button" type="button">Get quote!</button>
      <div id="data-container">
        <p class="data"></p>
      </div>
    </div>
    ```
  </Tab>

  <Tab tabId="1" title="module.js">
    ```js theme={null}
    const dataButton = document.getElementById("data-button");
    const dataContainer = document.getElementById("data-container");

    dataButton.addEventListener("click", function (e) {
      console.log("Button clicked!");

      // Show loading state
      dataContainer.innerText = "Loading...";

      fetch("http://meowmix-2272014.hs-sites.com/hs/serverless/fetch-quote")
        .then(response => {
          if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
          }
          // Parse the JSON response
          return response.json();
        })

        .then(data => {
          console.log("Raw data received:", data);

          // Clear container
          dataContainer.innerText = "";

          // Create the paragraph element
          const newDataElement = document.createElement("p");
          newDataElement.innerText = `"${data.q}" — ${data.a}`;
          dataContainer.appendChild(newDataElement);
        });
    });
    ```
  </Tab>
</Tabs>
