The Contact Form is a lightweight, embeddable form designed for public websites where visitors are not logged in. Visitors provide their name, email, and message. Submissions appear in your Helpdesky dashboard under Messages.
Contact Form vs Ticket Center: The Contact Form is for anonymous visitors on public pages. No authentication is required. The Ticket Center is for authenticated users inside your application who need to view and manage their support conversations.
The form is a single JavaScript file (contact-form.js) that renders itself into a container element on your page. It handles its own styling, validation, submission, and success state. No framework dependencies are required.
Quick Start
Get the contact form on your website in two minutes.
Enable messaging. In your Helpdesky dashboard, go to Messages and make sure messaging is turned on. The toggle is at the top of the Messages page.
Add the embed code. Open Embeds > Contact Form in the dashboard’s top navigation. Copy the embed code and paste it into your website's HTML where you want the form to appear:
<div id="hdh-contact-form"></div>
<script src="https://helpdesky.io/contact-form.js"
data-helpdesk-id="YOUR_HELPDESK_ID"></script>
Tip: The embed code in your dashboard already has your helpdesk ID filled in. Just copy and paste it directly.
Done. The form will automatically render in the container div. When a visitor submits, it creates a new conversation in your Messages inbox. You can reply from the dashboard, and your response will be emailed to the visitor.
Data Attributes
Configuration options are passed via the script tag.
| Attribute | Required | Description |
|---|---|---|
data-helpdesk-id |
Yes | Your helpdesk's unique identifier. Found in the embed code on the Contact Form dashboard page. |
data-container |
No | The ID of the container element. Defaults to hdh-contact-form. Use this if you need a different container ID. |
data-align |
No | Form alignment: left, center (default), or right. The Alignment saved in the dashboard is applied when the form loads and takes precedence over this attribute; the dashboard's embed code already carries the matching value. |
data-max-width |
No | Maximum width of the form. Defaults to 560px. Accepts any valid CSS value. The configuration saved in the dashboard is applied when the form loads and takes precedence over this attribute. |
Example with all attributes:
<div id="my-support-form"></div>
<script src="https://helpdesky.io/contact-form.js"
data-helpdesk-id="YOUR_HELPDESK_ID"
data-container="my-support-form"
data-align="left"
data-max-width="480px"></script>
Customization
Everything about the form's look and wording is set on the Contact Form page of your dashboard (Embeds > Contact Form). Settings are saved to your helpdesk and applied whenever the form loads, so the embed code never changes. The preview panel on the right updates as you type, and Save Settings publishes the change.
Appearance
| Setting | Default | Description |
|---|---|---|
| Accent Style | Accent Gradient | Paints the submit button with the accent gradient or with the Primary Color from your Branding settings. |
| Button Text | Send message | The text on the submit button. |
| Button Colour | Blank (follows Accent Style) | Overrides the branding colour for this form's button. Use the picker or enter a 6 digit hex value. |
| Button Text Colour | Blank (inherits from Branding) | Overrides the global button text colour for this form's button. |
| Label Colour | Blank (dark grey) | Text colour of the Name, Email, Message and custom field labels. |
| Use Branding Background | Off | Applies the background colour from your Branding page to the form container. |
| Background Colour | Blank (white) | A custom background colour for the form container. Ignored while Use Branding Background is on. |
| Success Heading | Message sent successfully | The heading shown after a successful submission. |
| Success Message | Thank you for reaching out. We’ll get back to you as soon as possible. | The body text shown after a successful submission. |
| Name Label / Name Placeholder | Name / Your full name | Label and placeholder of the name field. |
| Email Label / Email Placeholder | Email / you@example.com | Label and placeholder of the email field. |
| Message Label / Message Placeholder | Message / How can we help you? | Label and placeholder of the message field. |
Because every label, placeholder, button and success text is editable, the form can be in any language. There is no automatic translation; you type the words you want, and a blank field keeps the default.
Use Button Text to change the wording on the submit button, for example “Send message” or “Contact support”. The preview panel on the right shows how the form looks as you adjust its appearance.
Edit the highlighted Button Text field to change the form’s submit button label.
Layout
| Setting | Default | Description |
|---|---|---|
| Alignment | Center | How the form sits in its container: Left, Center or Right. The dashboard's embed code carries the matching data-align value. |
| Hide outer border | Off | Removes the outer border, background and shadow so the embed blends into your page. |
Custom Fields
The Custom Fields section adds extra inputs for structured information such as an order number, a department or a phone number. Five field types are available: Text, Text Area, Dropdown (one option per line), Checkbox and Number. Each field has a label and a placeholder, can be marked Required, and can be moved up or down in the list.
Custom fields always render between Email and Message, and their values arrive with the conversation in your inbox. The same fields are shared with the Ticket Center, so you define them once. The public form has no file attachments and no separate subject field; a short Text field works well as a subject line if you need one.
Custom CSS snippets
Under Custom CSS, the View example snippets button opens the CSS Snippet Library: Brand Colors, Dark Mode / Dark Background, Rounded / Pill Style, Flat / Minimal, Custom Fonts, Full-Width Bold Button and Compact Form. Copy one into the Custom CSS textarea, adjust the values to your brand, and save. The Custom CSS section further down lists the selectors and explains why most declarations need !important.
Email Notifications
When you reply to a contact form conversation, the visitor receives an email notification at the address they submitted. Notifications are delayed by 60 seconds and can be skipped if the visitor reads the reply before the email is sent. You can also send emails immediately using the Send Instantly toggle. See Email Notification Timing for full details.
Let an AI Agent Answer the Form
Every submission is a conversation in Messages, which means a Helpdesky AI agent can answer it. Create one under Inbox → AI Agents (beta). Agents draft from your published articles and data sources, and they run on your own AI provider key saved under Settings → AI Settings; until a key is added, an agent can be set up but nothing runs.
The Mode section decides who presses send:
- Review drafts a reply and waits for one click approval. The draft appears in the thread marked Waiting for your approval, with Send as the agent's name, Edit and Discard. Nothing reaches the visitor until a teammate approves it, and pacing does not apply.
- Autopilot sends on its own within the pacing and guardrails you set. The thread shows that the agent is handling the conversation, with Pause and Hand back, and replying yourself pauses the agent.
Then open Behaviour → Channels and switch on Contact form. The contact form belongs to the Tickets & email channel group, where replies are expected to take a while, so the Reply delay is measured in minutes: Instantly, Within a few minutes, Like a busy human or a Custom range (minutes). If a teammate replies during the delay, the agent's pending reply is cancelled rather than sent on top.
The visitor receives the agent's reply by email like any other reply, with the same notification timing. Start with Set Up Your First AI Agent, then tune delays, daily caps and hand off rules with the guardrails and pacing guide.
Cloudflare Turnstile
Turnstile adds bot protection to your contact form. Without it, your form has no spam prevention and you may receive large volumes of unwanted submissions. Turnstile is free for unlimited use and we strongly recommend setting it up.
Create a Turnstile widget. Go to the Cloudflare Turnstile dashboard and create a new widget. You do not need to use Cloudflare as your DNS provider. Turnstile works with any domain.
Add your domain. In the widget settings, add the domain(s) where the contact form will be embedded to the Allowed Hostnames list. For example, yoursite.com and www.yoursite.com.
Enter the keys in your dashboard. Copy the Site Key and Secret Key from Cloudflare and paste them into the Turnstile section on the Contact Form dashboard page. The Site Key is embedded in the form (public). The Secret Key is used to verify submissions on the server (private, never shared).
Save. Click Save Settings. The Turnstile challenge will automatically appear on your contact form. Submissions that fail verification will be rejected.
For a step by step walkthrough with screenshots, see Setting Up Cloudflare Turnstile.
Custom CSS
Add custom CSS in the Custom CSS section of the Contact Form dashboard page, or start from the View example snippets library. Your CSS is injected as a style element inside the form's shadow root, after the built in styles. Most built in styles are set inline on the elements, so add !important to any declaration that does not seem to apply.
Available selectors: .hdh-cf-form (the form card), .hdh-cf-form label, #hdh-cf-name, #hdh-cf-email, #hdh-cf-message, .hdh-cf-submit, .hdh-cf-success and .hdh-cf-error. Custom fields use #hdh-cf- followed by the field id.
Example: change border radius and add a brand color:
.hdh-cf-form {
border-radius: 8px !important;
border-color: #6366f1 !important;
}
.hdh-cf-submit {
background: #6366f1 !important;
border-radius: 8px !important;
}
.hdh-cf-submit:hover {
background: #4f46e5 !important;
}
Example: make the form full width with squared corners:
.hdh-cf-form {
max-width: 100% !important;
border-radius: 0 !important;
border: none !important;
box-shadow: none !important;
padding: 0 !important;
}
.hdh-cf-form input,
.hdh-cf-form textarea {
border-radius: 4px !important;
}
.hdh-cf-submit {
border-radius: 4px !important;
}
Restrict Where the Form Loads
You can limit which websites are allowed to embed your contact form. Open Settings > Messages in the dashboard and add your domains to the Allowed Embed Domains setting. Subdomains are included automatically, and leaving the list empty allows every domain. For the full guide, see Restrict Embeds to Specific Domains.
Troubleshooting
Form not appearing. Check that the container element (<div id="hdh-contact-form">) exists in the DOM before the script loads. The script must be placed after the container div, not in the <head>. Also verify that your data-helpdesk-id is correct.
"Contact form not available" error. This means either messaging is disabled for your helpdesk, or the messaging feature has not been enabled for your account. Two conditions must both be true: messaging must be enabled in your dashboard (Messages page toggle), and the messaging feature must be activated for your account.
Turnstile showing "Unable to connect to website". This happens when the domain the form is running on is not in your Turnstile widget's allowed hostnames list. Go to your Cloudflare Turnstile dashboard, edit your widget, and add the domain where the form is embedded. If you are testing locally (e.g. localhost:3000), you can temporarily remove the Turnstile keys from your Contact Form settings to disable the challenge during development.
Form values cleared on error. This was a known issue that has been fixed. The form now preserves entered values when an error occurs. If you are seeing this behavior, make sure you are loading the latest version of the script by adding a cache busting query parameter: contact-form.js?v=10, the version the dashboard's embed code carries today.
Form looks different from the preview. The form renders inside a Shadow DOM, so your website's stylesheet does not reach it and a CSS reset around the container changes nothing. Style it from the Custom CSS section on the Contact Form page instead; most built in styles are inline, so declarations usually need !important. The one piece outside the shadow root is the Turnstile challenge, which sits in your page below the form and is styled from your own stylesheet. The dashboard preview is an approximation, and the form uses its own system font stack, so use the Custom Fonts snippet if you want it to match your site's typeface.