Marketing signup
Build custom newsletter and SMS signup forms with subscribeToMarketing(), without requiring customer login.
Use tiquo.subscribeToMarketing(input) to collect newsletter or SMS opt-ins from a custom website form. Email is the only required field. The visitor does not need to sign in, and the submission creates no enquiry.
Complete setup first: enable Website SDK, configure your website domain and initialise Tiquo with your public key. Your application owns the form, labels, consent text and feedback.
Subscribe to marketing
import { Tiquo } from '@tiquo/dom-package';
const tiquo = new Tiquo({ publicKey: 'pk_dom_your_public_key' });
await tiquo.subscribeToMarketing({
email: 'alex@example.com',
emailOptIn: true,
});
// A fuller submission; only email is required.
await tiquo.subscribeToMarketing({
email: 'sam@example.com',
firstName: 'Sam',
lastName: 'Smith',
phone: '+447911123456',
emailOptIn: true,
smsOptIn: true,
});The TypeScript signature is subscribeToMarketing(input: SubscribeToMarketingData): Promise<SubscribeToMarketingResult>. Both types are exported from @tiquo/dom-package.
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. |
Use the phone number field helper (TiquoPhone.createField()) for the phone input so international numbers are formatted correctly, and send its e164 value and countryCode.
| 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. |
Opt-in values must be booleans, not strings such as "true" or "on". 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.
Custom website form
Add this HTML to your page:
<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>After the form exists in the DOM, bind it using your configured tiquo instance:
function bindMarketingForm(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;
}
});
}
bindMarketingForm(tiquo);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.
SDK failures throw TiquoAuthError with code SUBSCRIBE_TO_MARKETING_FAILED. HTTP failures also include statusCode; a locally detected missing email has no HTTP status. See Utilities and errors.
Related methods
Use authenticated profile updates when a signed-in customer needs to change profile details or opt out. Use createEnquiry() when the form should create an enquiry. Website builders can use the Hosted Package automatic HTML form. The data-tiquo-form bindings are handled by the hosted script and do not require an npm DOM Package update.