Skip to main content

The embed script

What the two lines of form code do on a page, the attributes the script reads, the event it sends and what it needs from the page.

The embed is two lines of HTML: a placeholder element and one script. The script draws TradeSender's enquiry form inside the placeholder and posts what people send to the enquiry form's address.

For the steps a website owner follows, see Add the form to your website.

The two lines

<div data-tradesender-enquiry="YOUR_FORM_KEY"></div>
<script async src="https://app.tradesender.co.uk/enquiry.js"></script>
  • The div is where the form appears. Its data-tradesender-enquiry attribute holds the workspace's form key.
  • /enquiry.js is one classic script with no dependencies. It is not a module.
  • Put the script on a page once, however many placeholders the page has. Loading it twice does no harm.

What the script does

  1. When the page has been parsed, it finds every element with a data-tradesender-enquiry attribute. If the page is already parsed when the script runs, it does this at once.
  2. It skips an element whose attribute is empty, and one that already has a shadow root.
  3. It attaches an open shadow root to the element and draws the form there, with the form's own styles.
  4. When someone sends the form, it checks for a name and for a phone number or an email address. Then it posts to https://app.tradesender.co.uk/api/v1/public/enquiry_forms/ followed by the key.
  5. On success it puts a thank-you in place of the form and dispatches an event.

What it posts

A multipart/form-data body with no credentials and one header, Accept: application/json. A browser sends that to another origin without a preflight.

PartValue
name, phone, email, address_line_1, city, postal_code, messageWhat was typed, trimmed. An empty field is left out.
photos[]Each chosen photo.
_pagewindow.location.href, so the business sees which page the enquiry came from.
_gotchaThe hidden honeypot field, which a person leaves empty.

The script gives up after 2 minutes and tells the visitor to try again.

Photos

The form takes up to 5 photos: JPEG, PNG, WebP or HEIC. Before sending, the browser scales each one down to at most 2,048 pixels on its long edge and saves it as a JPEG. A JPEG already within that size goes unchanged, and so does a photo the browser cannot read, such as HEIC outside Safari. A photo still over 10 MB after that is refused in the form.

Attributes

AttributeRequiredWhat it sets
data-tradesender-enquiryYesThe workspace's form key.
data-accentNoA CSS colour for the Send enquiry button and for the outline of the field in focus. Without it they are #006c00.

The script reads no other attribute and takes no other option. It reads both when it draws the form, so changing them afterwards does nothing.

Add a placeholder after the page has loaded

The script defines one global, TradeSenderEnquiry, with one function. TradeSenderEnquiry.mount() draws the form in every placeholder that does not have one yet. Call it after you add a placeholder from your own code, as a single-page app does.

const host = document.createElement('div');
host.dataset.tradesenderEnquiry = 'YOUR_FORM_KEY';
document.querySelector('#contact').append(host);

window.TradeSenderEnquiry.mount();

To take a form away, remove its element.

The event

When TradeSender accepts an enquiry, the script dispatches tradesender:enquiry-sent on the placeholder element. The event bubbles and carries no detail. Nothing is dispatched when a send fails.

document.addEventListener('tradesender:enquiry-sent', (event) => {
  // event.target is the placeholder the enquiry was sent from.
});

Use it to count a conversion in your own analytics. The script itself sets no cookies, stores nothing in the browser and loads nothing else.

Styling

The form lives in a shadow root. The page's CSS does not apply inside it, and the form's CSS does not leak out.

What the form inherits from the placeholder element:

  • font: the family and size. Fields and the button use it too, and labels are set a little smaller and bolder.
  • color: labels and typed text. Field borders are the same colour at 30% strength.

What the form sets for itself:

  • Text is aligned left.
  • Fields have a transparent background, a border and an 8 pixel radius.
  • Paired fields sit side by side when each has at least 180 pixels, and stack otherwise.
  • The Send enquiry button is the accent colour with white text.
  • A problem appears in a red box on white.

The only styling hook is data-accent. There are no CSS custom properties for the page to set, no part attributes and no slots. Setting --accent on the page has no effect, because the form sets it inside the shadow root.

The placeholder is an ordinary block element. Give it a width, a margin or a font as you would any div. Anything you put inside it stops being displayed once the form is drawn.

The fields, their order and their wording are fixed, and the wording is English. For a form of your own design, post to the enquiry form's address yourself.

What the visitor may be told

MessageWhen
"Add your name."Your name is empty.
"Add a phone number or an email address."Phone and Email are both empty.
"back-hedge.pdf isn't a JPEG, PNG, WebP or HEIC photo."A chosen file is not one of those types.
"You can send up to 5 photos."More than 5 photos were chosen.
"back-hedge.jpg is larger than 10 MB."A photo is too large even after shrinking.
"Too many enquiries have been sent from here. Please try again later, or contact us another way."The address answered 429.
"This form is no longer in use. Please contact us another way."The address answered 404: the key is mistyped or has been replaced.
"Couldn't send your enquiry. Check your connection and try again."The request failed or took over 2 minutes.
"Thanks, your enquiry has been sent."The enquiry was accepted.

For any other refusal the form shows the detail the address sent back, or "Couldn't send your enquiry. Please try again." when there is none.

What it needs from the page

The page must run JavaScript. If the page sends a Content-Security-Policy, the policy needs these. Where a directive is absent, default-src stands in for it.

DirectiveMust allowWhy
script-srchttps://app.tradesender.co.ukThe script is loaded from there.
connect-srchttps://app.tradesender.co.ukThe form posts there with fetch.
style-src'unsafe-inline'The form's styles are a style element the script adds to the shadow root. Without this the form appears unstyled.

Load the script from app.tradesender.co.uk. It posts to the origin it was loaded from, so a copy on your own server would post to your server.

Do not add an integrity attribute. The file is rebuilt when TradeSender updates the form, and a fixed hash would then stop it loading.

What stays the same

Pages that paste the two lines are rarely edited again, so three things are kept as they are:

  • the script's address, https://app.tradesender.co.uk/enquiry.js
  • the data-tradesender-enquiry attribute
  • where the form posts

The file is served so that a browser checks for the current one on each visit. There is no version to pin, and a fix to the form reaches every website without anyone pasting new code.

Checked against the app on 8 October 2026. Still stuck? Ask usAsk us.