Customer Booking Form

You embed the booking form with one script tag and one <jims-customer-booking> element, then set its behaviour with a JSON settings attribute. It works on any platform that lets you add HTML: WordPress, Shopify, custom sites.

This guide covers version 1.20.3 of the form.

Quick start

Two steps: load the script once per page, then place the element where the form should appear.

  1. Add the script before the closing </body> tag so it does not block page rendering.
<script type="module" crossorigin src="https://cdn.jims.net/customerbookingform/customerbookingform.js"></script>
  1. Place the element. With no settings it shows the full form: country, division, services, then contact details.
<jims-customer-booking></jims-customer-booking>

To configure it, pass JSON in the settings attribute. You only include the options you want to change; everything else keeps its default.

<jims-customer-booking settings='{
    "divisions": { "selected": 1, "show": false },
    "complete": { "redirect": "https://example.com/thank-you" }
}'></jims-customer-booking>

The script URL always serves the latest release, so you get fixes without changing your embed.

Writing the settings attribute

  • Wrap the attribute in single quotes and use double quotes inside the JSON.
  • Invalid JSON stops the form from rendering. Check it in a JSON validator if the form does not appear.
  • An apostrophe in your own text (for example a custom heading) ends the attribute early. Write it as &#39;.
  • Objects merge with the defaults, key by key. Arrays replace the default array entirely.
  • You can also set settings from JavaScript: document.querySelector('jims-customer-booking').settings = { core: { popup: true } };

Where to find IDs

Configuration reference

Every option below is optional. Paths use dot notation: core.popup means {"core": {"popup": ...}}.

Behaviour and layout

SettingTypeDefaultWhat it does
core.popupbooleanfalseShows the form as a full-screen popup instead of inline. See Display modes.
core.work_guaranteebooleantrueShows the Jim’s work guarantee button and dialog.
header.showbooleantrueShows the header (logo and step breadcrumbs). false gives a compact inline form.
header.logo.urlstring (URL)Jim’s Local Expert logoLogo image shown in the header.
header.logo.divisionnumber or "id:slug"nullUses that division’s logo instead of url.
header.logo.showbooleantruefalse hides the logo visually but keeps it for screen readers.
steps.showHeadingsbooleantrueShows step headings. false keeps them for screen readers only.
steps.showSearchbooleantrueShows the search box on the division and services steps.
footer.submitTextstringSubmitText on the final submit button.

Country and divisions

SettingTypeDefaultWhat it does
country.selectedstringauTwo-letter country code, for example au, nz.
country.showbooleantrueShows the country picker on the division step. Forced on when country.selected is empty.
divisions.selectednumber, string or "id:slug"nullPre-selects a division.
divisions.showbooleantruefalse skips the division step. Needs divisions.selected.
divisions.toShownumber[][]Only these divisions are listed, in this order.
fmsliststringemptyName of a custom FMS service list, for example MowingCustomList. Changes the divisions and services offered.

Services

SettingTypeDefaultWhat it does
services.selectednumber[][]Pre-selects services by ID.
services.showbooleannot setfalse skips the services step. Needs a division and services.selected.
services.multiplebooleantruefalse lets the customer pick only one service.
services.toHidenumber[][]Removes these services from the list.
services.sort"default", "alphabetical" or number[]"default"Order of ungrouped services. An array lists IDs in the order to show; others follow.
services.groupsobject[][]Groups services under headings. See Divisions and services.
services.showAllWhenGroupedboolean or "accordion"trueWith groups, adds an “All services” group for the rest. "accordion" makes it collapsible.

Contact details step

SettingTypeDefaultWhat it does
customer.showServicesbooleantrueShows the chosen services as pills above the fields.
customer.showFieldLabelsbooleanfalseShows labels above fields. By default only placeholders show.
customer.fields.business_name.showbooleantrueShows the business name field.
customer.fields.comments.showbooleantrueShows the job details field.
customer.fields.comments.valuestringemptyPre-fills the job details field.
customer.fields.subscribe.showbooleantrueShows the special offers opt-in.
customer.fields.<field>.labelstringsee WordingField label. Also placeholder and error.

First name, last name, email, phone and address are always shown and always required.

Completion

SettingTypeDefaultWhat it does
complete.redirectstring (URL)emptySends the customer to this URL after a successful booking. Supports placeholders.
complete.franchiseeVideostring (YouTube embed URL)Jim’s franchisee videoVideo on the confirmation screen when a franchisee takes the job.
complete.contractorVideostring (YouTube embed URL)Jim’s contractor videoVideo when a contractor takes the job.

Tracking and URL parameters

SettingTypeDefaultWhat it does
urlparamsstring[][]Allows these page URL parameters to change the form. See Display modes and behaviour.
utm.source, utm.medium, utm.campaign, utm.content, utm.termstringemptyUTM values sent with the booking. Page URL utm_* parameters override them.
core.googleAPIKeystringbuilt inGoogle Places key for address lookup. Only change if Jim’s asks you to.

Wording

Every piece of text can be replaced. Set the key to your own text.

SettingDefault text
divisions.content.headingSelect a division
divisions.content.search.labelSearch for a division
divisions.content.errorPlease select a division
services.content.headingSelect services
services.content.allgroupheadingAll services
services.content.errorPlease select one or more services
customer.content.headingYour details
customer.content.servicesSelected services
country.content.headingWhat country are you looking for work in?
core.content.apisubmitSubmitting your request, please do not close the screen
core.content.apierrorWe’re sorry, something unexpected has happened…
core.content.promoBannerRequest a quote today and you’re in this week’s {prize} Jim’s voucher draw…

The promotion banner shows only for Australia and New Zealand. Set core.content.promoBanner to "" to hide it. Search result messages accept {count} and {query}.

Divisions and services

Which steps the customer sees

The form skips steps you have already answered, but only when you also hide them.

You setSteps shown
Nothing, or divisions.show left trueDivision, services, contact details
divisions.show: false + divisions.selectedServices, contact details
Above + services.selected + services.show: falseContact details only

If you pre-select a division but leave divisions.show as true, the division step still shows with that division ticked.

With divisions.show: false and a division selected, the header uses that division’s logo and the form takes on the division’s colour.

Selecting a division

divisions.selected accepts 1, "1" or "40:fire-safety". A plain ID picks the main division. Use the id:slug form to pick an alias division that shares the ID, for example Jim’s Fire Safety under ID 40. header.logo.division accepts the same forms.

Restricting the division list

divisions.toShow lists division IDs as numbers, not strings. Divisions appear in the order given; IDs that don’t exist are ignored.

{ "divisions": { "toShow": [5, 1, 53, 37, 8] } }

Service groups

Each group has a heading, a services array of IDs, an optional content HTML string shown under the heading, and an optional accordion: true to make it collapsible. Services in a group show in the order you list them. A service can appear in more than one group. Groups with no matching services are left out.

{
  "divisions": { "show": false, "selected": 1 },
  "services": {
    "groups": [
      { "heading": "Popular", "content": "<p>Our most-booked jobs</p>", "services": [2147, 24] },
      { "heading": "Seasonal", "services": [26], "accordion": true }
    ],
    "showAllWhenGrouped": "accordion"
  }
}

Services not in any group go in a final “All services” group. Set showAllWhenGrouped to false to drop them, or "accordion" to collapse them. services.sort orders that final group and ungrouped lists only.

Upsells

Some services offer a second service from another division on an extra step (for example, service 344 offers service 2). Jim’s manages these rules; you cannot change them in settings.

Display modes and behaviour

Popup

With core.popup: true, the form stays hidden until the page URL hash is #jims. Any link to #jims opens it, and closing it removes the hash.

Place the element directly inside <body>, at the start or end, so page layout doesn’t clip it.

<body>
    <a href="#jims">Get a free quote</a>
    ...
    <jims-customer-booking settings='{"core":{"popup":true}}'></jims-customer-booking>
</body>

Use one popup booking form per page. It can share a page with a popup franchise enquiry form.

Compact inline form

For a small form in a sidebar or landing page, hide the header, headings and extras:

{
  "header": { "show": false },
  "core": { "work_guarantee": false },
  "steps": { "showHeadings": false }
}

Redirect after booking

complete.redirect sends the customer to your page after a successful booking, instead of the confirmation screen. Failed or incomplete bookings don’t redirect.

PlaceholderReplaced with
{division_id}Division ID, for example 1
{division_name}Division name, inserted as-is (not URL-encoded)
{service_ids}Comma-separated service IDs
{service_names}Comma-separated service names
{ "complete": { "redirect": "https://example.com/thanks?division={division_id}&services={service_ids}" } }

URL parameters

UTM parameters (utm_source, utm_medium, utm_campaign, utm_content, utm_term, or their camelCase forms) are always read from the page URL and sent with the booking.

Other parameters are ignored unless you list them in urlparams. This stops visitors changing the form from a link.

ParameterSetsExample
msgJob details text?msg=Front%20lawn
divisionId or divisiondivisions.selected, and hides the division step?divisionId=1
servicesservices.selected (comma-separated)?services=24,2147
countryCodecountry.selected?countryCode=nz
serviceListNamefmslist?serviceListName=MowingCustomList
{ "urlparams": ["msg", "divisionId", "services"] }

An unknown country code or service list name shows an error screen.

Examples

Copy the one closest to your page and adjust the IDs.

Division website: skip straight to services

<jims-customer-booking settings='{
    "divisions": { "selected": 1, "show": false }
}'></jims-customer-booking>

Service landing page: contact details only

<jims-customer-booking settings='{
    "divisions": { "selected": 1, "show": false },
    "services": { "selected": [24], "show": false },
    "customer": { "fields": { "comments": { "value": "Lawn mowing enquiry" } } }
}'></jims-customer-booking>

New Zealand site

<jims-customer-booking settings='{
    "country": { "selected": "nz", "show": false }
}'></jims-customer-booking>

Short form: fewest fields

<jims-customer-booking settings='{
    "header": { "show": false },
    "core": { "work_guarantee": false },
    "steps": { "showHeadings": false },
    "divisions": { "selected": 1, "show": false },
    "services": { "selected": [24], "show": false },
    "customer": { "fields": {
        "comments": { "show": false },
        "subscribe": { "show": false },
        "business_name": { "show": false }
    } }
}'></jims-customer-booking>

One service only, alphabetical list

<jims-customer-booking settings='{
    "divisions": { "selected": 1, "show": false },
    "services": { "multiple": false, "sort": "alphabetical" }
}'></jims-customer-booking>

Multi-division partner site

<jims-customer-booking settings='{
    "divisions": { "toShow": [1, 5, 8] },
    "header": { "logo": { "url": "https://example.com/partner-logo.svg" } }
}'></jims-customer-booking>

Campaign page reading the division from the link

<jims-customer-booking settings='{
    "urlparams": ["divisionId", "services", "msg"],
    "complete": { "redirect": "https://example.com/thanks?d={division_id}" }
}'></jims-customer-booking>

Link to it as https://example.com/quote?divisionId=1&services=24&utm_source=facebook.

Analytics events

The form pushes events to window.dataLayer, so Google Tag Manager can pick them up with a Custom Event trigger. You don’t need GTM installed for the form to work.

EventFires when
jcbf-step-changeThe customer moves to another step
jcbf-country-selectedThe country changes
jcbf-division-selectedThe division changes
jcbf-services-selectedThe selected services change
jcbf-address-rejectedThe customer rejects the address shown on the map
jcbf-contact-details-invalidSubmit is clicked with invalid details
jcbf-submitDetails are sent to Jim’s. Not yet a confirmed booking.
jcbf-submit-responseJim’s has replied to the submission
jcbf-submit-completeThe booking reached a franchisee or the call centre. Use this as your conversion.
jcbf-phone-clickA phone number is clicked
jcbf-work-guarantee-dialog-openedThe work guarantee dialog opens
jcbf-resetThe form is reset

The submit-response and submit-complete events include division (ID), services (IDs) and response (result code).

Styling

The form renders inside a shadow DOM, so your site’s CSS doesn’t change it and its CSS doesn’t leak into your page. Size and place it by styling the jims-customer-booking element itself. Colours come from Jim’s branding, or from the division when the division step is hidden.

Troubleshooting

SymptomCheck
Form doesn’t appearScript tag is on the page with type="module"; the settings JSON is valid; no unescaped apostrophe in the attribute.
Popup never openscore.popup is true and your button links to #jims.
Division step still showsSet divisions.show: false as well as divisions.selected.
Services step skipped when you wanted itYou hid divisions and pre-selected services. Add "services": {"show": true}.
Some services missingThey are in services.toHide, not in any group while showAllWhenGrouped is false, or not offered by that division.
divisions.toShow shows nothingIDs must be numbers (1), not strings ("1").
URL parameter ignoredAdd it to urlparams. UTM parameters need no setting.
Error screen on loadCheck countryCode or serviceListName values.
Redirect doesn’t happenThe URL must be absolute (https://…). Redirect runs only after a successful booking.
Logo doesn’t showheader.logo.url must be a public image URL, or the division must have a logo.

For anything else, contact the web team at Jim’s Group with the page URL.