GoodInbound

Embeddable Widgets

Booking widget#

Embed a full booking flow on any page. The widget handles date and time picking and the booking form.

<div id="booking-widget"></div>
<script src="https://cdn.goodinbound.com/widgets/booking.js"></script>
<script>
  GoodInbound.booking({
    projectSlug: "acme",
    eventTypeSlug: "consultation",
    container: "#booking-widget",
    theme: {
      primaryColor: "#1B4332"
    }
  });
</script>
Property Type Required Description
projectSlug string Yes Your project's URL slug
eventTypeSlug string Yes The event type to book
container string | HTMLElement Yes CSS selector or DOM element
theme.primaryColor string No Override brand color
hidden Record<string, string | string[]> No Prefill hidden (or visible) fields by field id. Wins over host-page query params.
ui { hideBanner?, hideBranding?, hideTitle?, hideIntro?, hideAvatar? } No Hide booking chrome for this embed. hideBranding works on every plan. URL hide_* flags also work.

Form widget#

Embed a form on your site. The widget renders each page in sequence and handles validation, submission, and the completion state.

<div id="form-widget"></div>
<script src="https://cdn.goodinbound.com/widgets/form.js"></script>
<script>
  GoodInbound.form({
    projectSlug: "acme",
    formSlug: "contact",
    container: "#form-widget",
    theme: {
      primaryColor: "#1B4332"
    }
  });
</script>
Property Type Required Description
projectSlug string Yes Your project's URL slug
formSlug string Yes The form's URL slug
container string | HTMLElement Yes CSS selector or DOM element
theme.primaryColor string No Override brand color
hidden Record<string, string | string[]> No Prefill hidden (or visible) fields by field id. Wins over host-page query params.
ui { hideBanner?, hideBranding?, hideTitle?, hideIntro?, hideMedia? } No Hide form chrome for this embed. hideBranding works on every plan.

Theme#

Both widgets accept a theme object to match your brand: colors, border radius, and fonts.

GoodInbound.booking({
  projectSlug: "acme",
  eventTypeSlug: "consultation",
  container: "#booking-widget",
  theme: {
    primaryColor: "#1B4332",
    borderRadius: "12px",
    fontFamily: "Inter, sans-serif"
  }
});

Both widgets are zero-dependency bundles under 6KB gzipped.

Prefill and hidden fields#

Hidden fields stay off the public screen but still accept values. Keys are field ids, not labels. Query values win over a field's default, and the widget's hidden option wins over the host page query string.

Share link

https://goodinbound.com/acme/contact?utm_source=newsletter&plan=pro

Embed with JS values

GoodInbound.form({
  projectSlug: "acme",
  formSlug: "contact",
  container: "#form-widget",
  hidden: {
    user_id: "usr_123",
    plan: "pro"
  }
});

Both widgets forward the host page query string into the iframe, so ?plan=pro on your site fills a plan field. The exceptions are embed, theme, and the keys the widget uses itself: gi_source, gi_journey, gi_page, gi_ref, gi_fbp, and gi_fbc. Booking links also accept reserved name, email, and notes when those ids are free. File fields cannot be prefilled.

Hide page chrome#

Form and event settings can hide the banner, title, intro, section image, avatar, and GoodInbound branding. A share link or embed can hide more with query flags, but a flag cannot unhide something the resource already hid. Hiding branding works on every plan.

Share link

https://goodinbound.com/acme/contact?hide_banner=1&hide_title=1

Widget

GoodInbound.form({
  projectSlug: "acme",
  formSlug: "contact",
  container: "#form-widget",
  ui: { hideBanner: true, hideTitle: true }
});

Flags are hide_banner, hide_branding, hide_title, hide_intro, hide_avatar, and hide_media. Custom CSS can target [data-gi-banner], [data-gi-title], [data-gi-intro], [data-gi-avatar], [data-gi-media], and [data-gi-branding].