Marketing signup
Build a custom newsletter or SMS signup form with the Hosted Package, without customer login.
Use data-tiquo-form="marketing-subscribe" to bind a newsletter or SMS signup form automatically, or call window.Tiquo.subscribeToMarketing(input) from your own JavaScript. Email is the only required field. Visitors do not need to log in, and the submission creates no enquiry.
Complete installation first, including your Website SDK public key and allowed website domain.
Subscribe to marketing
Call this after the hosted script has loaded:
await window.Tiquo.subscribeToMarketing({
email: 'alex@example.com',
emailOptIn: true,
});
// A fuller submission; only email is required.
await window.Tiquo.subscribeToMarketing({
email: 'sam@example.com',
firstName: 'Sam',
lastName: 'Smith',
phone: '+447911123456',
emailOptIn: true,
smsOptIn: true,
});Accepted fields
Pass fields directly in the input object, without a customer wrapper. Only email is required.
| Field | Type | Required | Behaviour |
|---|---|---|---|
email | string | Yes | Matches a customer within your organisation or creates one. Maximum 254 characters. |
firstName | string | No | Saved only for a new customer. Maximum 100 characters. |
lastName | string | No | Saved only for a new customer. Maximum 100 characters. |
phone | string | No | Saved only for a new customer. Use an international number such as +447911123456, or supply phoneCountry for national format. Maximum 64 characters. |
phoneCountry | string | No | Supported two-letter country code such as GB or FR for the submitted phone. |
emailOptIn | boolean | No | true enables Marketing Opt-In on a new or existing customer. |
smsOptIn | boolean | No | true enables SMS Opt-In on a new or existing customer. |
honeypot | string | No | Hidden spam-trap field. Real visitors leave it empty. Maximum 500 characters. |
When calling subscribeToMarketing() directly, opt-in values must be booleans, not strings such as "true" or "on". Automatic HTML forms convert their opt-in controls to booleans before submission. Custom customer parameters, customer IDs, organisation IDs, profile photos and other profile fields are not accepted. The configured public key selects the organisation.
Creating and updating customers
| Submission | Result |
|---|---|
| Email has no customer in the organisation | Creates a customer with the supplied names and phone, if provided. Unselected opt-ins default to false. |
| Email matches an existing customer | Applies only opt-ins explicitly set to true. All other profile data stays unchanged, including blank names or phone fields. |
An opt-in is false or omitted | Leaves an existing preference unchanged. It never unsubscribes someone. |
| An opt-in is already enabled | Keeps it enabled and preserves its original opt-in date. |
| Email belongs to a soft-deleted profile | Does not recreate the deleted customer. |
Email matching uses Tiquo's existing email normalisation and is scoped to your organisation. Tiquo records the opt-in date and the dom_marketing source. A submission with only an email can create a profile without opting it into either channel.
SMS opt-in may be recorded without a phone number, but sending SMS still requires a usable number on the customer profile. A phone supplied for an existing customer is ignored, even if their profile has no phone yet.
Opt-ins apply immediately from the submitted email and checked boxes. No login, OTP or ownership confirmation is required. This trusts the submitted contact information; abuse protection does not verify who owns it.
The method creates no enquiry, establishes no login session and does not identify the visitor in website analytics. Analytics consent and customer marketing preferences are separate.
Automatic hosted form
Requires Hosted Package 1.3.0 or newer. Check window.Tiquo.version after installation. An npm DOM Package update is not required for this binding.
<form data-tiquo-form="marketing-subscribe">
<label>Email <input data-tiquo-marketing="email" type="email" autocomplete="email" required></label>
<label><input data-tiquo-marketing="emailOptIn" type="checkbox"> Send me email marketing</label>
<label><input data-tiquo-marketing="smsOptIn" type="checkbox"> Send me SMS marketing</label>
<input data-tiquo-marketing="honeypot" type="text" hidden tabindex="-1" autocomplete="off">
<button type="submit">Sign up</button>
<p data-tiquo-message role="status"></p>
</form>No custom submit handler is needed. The hosted script prevents duplicate submissions, sets the submit button's loading state, and displays success or error messages in data-tiquo-message.
Every field in the accepted fields table can use data-tiquo-marketing="FIELD". Use firstName, lastName, phone, and phoneCountry for optional customer details. Add data-tiquo-phone-field to the phone input to use the phone number field helper, which formats international numbers correctly and supplies the selected country automatically. Disabled fields are omitted. Checkboxes send true or false; other opt-in controls only send true when their value is "true". Start opt-in checkboxes unchecked.
Forms emit bubbling tiquo:marketing-subscribed with { success: true } or tiquo:marketing-error with { error } in event.detail. A success response remains an acknowledgement and does not expose customer information.
See HTML form bindings for all five form types, shared controls, and events.
Custom website form
Place the following in your page or website-builder custom-code block. It works with the deferred hosted script from the installation guide: the handler waits until deferred scripts have loaded.
Use this JavaScript alternative with an older hosted script or when your application needs to own submission. It does not use data-tiquo-form; do not combine its custom handler with the automatic binding on the same form.
<form id="marketing-signup">
<label>
Email
<input name="email" type="email" autocomplete="email" required>
</label>
<label>
<input name="emailOptIn" type="checkbox">
Send me email marketing
</label>
<input name="website" type="text" hidden tabindex="-1" autocomplete="off">
<button type="submit">Sign up</button>
<p role="status" aria-live="polite"></p>
</form>
<script>
function bindMarketingForm() {
const tiquo = window.Tiquo;
const form = document.querySelector('#marketing-signup');
if (!form) return;
const button = form.querySelector('button[type="submit"]');
const message = form.querySelector('[role="status"]');
let submitting = false;
form.addEventListener('submit', async (event) => {
event.preventDefault();
if (submitting) return;
const fields = new FormData(form);
submitting = true;
button.disabled = true;
message.textContent = '';
try {
await tiquo.subscribeToMarketing({
email: String(fields.get('email') || ''),
firstName: String(fields.get('firstName') || '') || undefined,
lastName: String(fields.get('lastName') || '') || undefined,
phone: String(fields.get('phone') || '') || undefined,
phoneCountry: String(fields.get('phoneCountry') || '') || undefined,
emailOptIn: fields.has('emailOptIn'),
smsOptIn: fields.has('smsOptIn'),
honeypot: String(fields.get('website') || ''),
});
message.textContent = 'Thanks — your request has been received.';
} catch (error) {
message.textContent = error instanceof Error
? error.message
: 'Unable to submit. Please try again later.';
} finally {
submitting = false;
button.disabled = false;
}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', bindMarketingForm, { once: true });
} else {
bindMarketingForm();
}
</script>If your website builder loads Tiquo dynamically instead of using the installation guide's deferred script, call bindMarketingForm() after that script's load event.
For a fuller form, add any of these fields inside the same form. The submit handler already includes them, and none is required:
<label>First name <input name="firstName" autocomplete="given-name"></label>
<label>Last name <input name="lastName" autocomplete="family-name"></label>
<label>Phone <input name="phone" type="tel" autocomplete="tel" placeholder="+447911123456"></label>
<label><input name="smsOptIn" type="checkbox"> Send me SMS marketing</label>For national-format phone input, include a phoneCountry input or country selector using two-letter values such as GB. Only add that value when it reflects the selected phone country. Keep your consent text specific to the communication channel.
Response and errors
Successful requests return only:
{ success: true }The response does not include a customer ID, profile, opt-in values, or whether the customer already existed. Screened spam receives the same response without customer or consent writes, so success is an acknowledgement rather than a way to inspect a profile.
| HTTP status | Meaning |
|---|---|
400 | Missing or invalid email, invalid field types, unsupported fields or invalid phone format. |
403 | Invalid public key, disabled Website SDK or missing/unapproved Origin. |
413 | Request body exceeds 8 KiB. |
429 | Rate limit exceeded. Stop automatic retries and let the visitor try later. The endpoint sends Retry-After: 600. |
500 | Subscription temporarily unavailable. |
Abuse protection
Every submission requires an enabled Website SDK integration and a valid HTTP(S) browser Origin matching an allowed website domain. Requests use POST /api/client/v1/marketing/subscribe; the package supplies your public key automatically.
Server limits apply over a 10-minute window:
| Scope | Limit |
|---|---|
| Organisation | 60 requests |
| Organisation and IP | 20 requests |
| Organisation and normalised email | 5 requests |
| Organisation and normalised submitted phone | 5 requests |
Spam screening checks disposable email addresses, reserved test phone numbers, markup and filled honeypots. Screened submissions still consume quota. Keep the honeypot blank and start marketing checkboxes unchecked.
A public key and Origin are not sender authentication: scripts can forge Origin and forwarded IP values. The organisation limit also applies when those values change. These controls reduce abuse; they do not guarantee that every submission comes from a real person.
Vercel BotID is not currently enforced by this endpoint.
The returned promise rejects on validation, network or HTTP errors. The automatic form displays those errors and emits tiquo:marketing-error. If you call the method directly, use try/catch to display feedback; direct calls do not emit HTML form events.
Related methods
Use an authenticated profile form when customers need to edit their details or uncheck an existing opt-in. Use enquiry forms when a submission should create an enquiry. Tiquo.setConsent() controls website analytics consent, not email or SMS preferences.
For applications with an npm build, see DOM Package marketing signup.