Integrations

Configure integrations such as Google Sheets and webhooks on your self-hosted HeyForm.


Integrations send every new submission to another service, or add a service to the public form page. Form owners set them up from a form's Integrations tab. Some integrations work out of the box, while others need the server to be configured first.

In this guide example.com will be used to represent the location you are hosting HeyForm, it should be replaced with the correct value.

IntegrationWhat it doesServer configuration
WebhookSends each submission to a URLNone
Privatus AnalyticsAdds cookie-free analytics to the public form pageNone
Google SheetsAdds each submission as a row in a Google spreadsheetEncryption key and Google OAuth

An integration that is missing its configuration is hidden from the Integrations tab.

Encryption key

Integrations that connect an account or store an API key save those credentials encrypted with INTEGRATION_ENCRYPTION_KEY. Without it, these integrations are unavailable and the server logs a warning at startup. Webhooks and Privatus Analytics keep working.

Generate a long random value:

openssl rand -base64 32
INTEGRATION_ENCRYPTION_KEY=
Warning

Keep this key safe and don't change it casually. If it's lost, every connected account and API key has to be entered again. It's separate from FORM_ENCRYPTION_KEY, so rotating either never breaks the other.

Rotate the key

  1. Set INTEGRATION_ENCRYPTION_KEY_PREVIOUS to the current key and INTEGRATION_ENCRYPTION_KEY to a new one, then restart. The previous key is only used to read existing values.
  2. Re-encrypt the values still on the old key. The command is safe to run while the server is running, and to run again:
    # Docker or built server
    node dist/src/cli/reencrypt-integration-secrets.js
    
    # Source checkout
    pnpm --filter ./packages/server integrations:reencrypt
    
  3. Remove INTEGRATION_ENCRYPTION_KEY_PREVIOUS and restart.

Google Sheets

Google Sheets uses one OAuth client for the whole installation. You register it once, then form owners only click Connect Google account and sign in. Connected accounts belong to the workspace, so every member can use them.

Create a Google OAuth client

In the Google Cloud console, in one project:

  • Go to APIs & Services → Library and enable the Google Sheets API
  • Configure the OAuth consent screen, then set its publishing status to In production, or choose Internal if all users are in your Google Workspace
  • Go to APIs & Services → Credentials, click Create credentials → OAuth client ID and choose Web application
  • Add “Authorized redirect URIs”: https://example.com/api/integrations/oauth/callback
  • Make a note of the “Client ID” and “Client secret”
Important

A consent screen left in Testing makes Google expire connections after 7 days, so users would have to reconnect every week. An unverified app in production is fine for your own users. They see an “unverified app” warning when they connect.

The redirect URI must match APP_HOMEPAGE_URL exactly, including the scheme, host and port.

Environment variables

Add the values noted above to the following environment variables, then restart HeyForm:

APP_HOMEPAGE_URL=https://example.com
INTEGRATION_ENCRYPTION_KEY=
GOOGLE_INTEGRATION_CLIENT_ID=
GOOGLE_INTEGRATION_CLIENT_SECRET=

These are separate from GOOGLE_LOGIN_CLIENT_ID and GOOGLE_LOGIN_CLIENT_SECRET, which are used for login with Google.

Webhooks to a private network

To protect your server, webhooks can't reach localhost or private network addresses (for example 10.0.0.0/8, 192.168.0.0/16 or 127.0.0.1). Saving such a URL fails with “Private network URLs are not allowed”.

This also happens when a proxy or VPN on the server uses fake-IP DNS, which resolves every domain to an address in 198.18.0.0/15. Exclude the webhook's domain from fake-IP in the proxy's settings.

To send webhooks to services on your own network, set:

ALLOW_PRIVATE_OUTBOUND=true
Warning

With this enabled, any form owner can make your server send requests to your internal network, including databases and cloud metadata endpoints. Only enable it when you trust everyone who can create forms.

Troubleshooting

  • An integration doesn't appear: check that INTEGRATION_ENCRYPTION_KEY and the provider's client ID and secret are set, then restart HeyForm.
  • Google shows “redirect_uri_mismatch”: the redirect URI in Google Cloud doesn't match APP_HOMEPAGE_URL + /api/integrations/oauth/callback.
  • An integration says it needs reconnecting: the account's access was revoked or expired, or the encryption key changed. Connect the account again. Submissions received in the meantime are sent once it's reconnected.