doc-site
Architecture

Booking and orders

How a camp booking moves from the product page, through the booking form and checkout, into Zoho CRM and the customer's inbox.

A booking is a Shopify cart line with the participant's details stored as line item properties. Shopify takes payment, and the booking only reaches Zoho once Zapier passes the paid order to shopify-zoho-integration.

From product page to cart

The Book camp button on the product page opens the booking form. The form calls Google Places for school search, shopify-zoho-integration for club search and asc-api-membership-pass for saved children, then adds one cart line per participant and sends the customer to checkout.

  1. The customer picks a camp on a sport or city page and lands on the product page with that variant selected. Every product page URL carries ?variant=, and the theme.product layout redirects to add it if it is missing.
  2. The customer chooses how many participants to book, up to 10 and never more than the variant's stock, and clicks Book Camp. The button is disabled when the variant is sold out or out of season.
  3. The booking form opens over the page. It shows one step per participant, with two parts: participant details, then playing experience.
  4. A logged-in customer can pick a child saved from an earlier booking instead of typing the details again.
  5. When the last participant is complete, the form adds one cart line per participant, each with quantity 1, and sends the customer to /cart.
  6. If the customer typed new children rather than choosing saved ones, the form also saves each child to their account. This request is not awaited, so the page can move to the cart before every save finishes.

A camp card can open the booking form directly. When the section setting "Reveal booking form when a camp card is selected" is ticked, the card link adds &start_booking to the product URL and the form opens on page load.

The participant fields and the property names they produce are listed in Booking line item properties.

Cart

The live cart is the "ASC New Cart Layout" section. For each line whose product is tagged sport it shows the participant details and the membership pass button. Other products show a simple product line.

The cart also shows:

  • an upsell block, driven by the variant metafield Upsell Product;
  • FAQs, reviews and selling points, which are blocks in the cart section rather than metaobjects;
  • a checkout button that sends a checkout_clicked analytics event before it submits.

Membership passes are covered in Membership passes.

From order to Zoho

A paid Shopify order triggers Zapier, which calls shopify-zoho-integration. The service writes bookings and participants to Zoho CRM and sends the confirmation email through Mailgun. A scheduled job calls the service daily for 7-day and 2-day reminders.

When checkout completes, three Zapier zaps start from the new order.

ZapCallsResult
Shopify → Zoho via APIPOST /ordersBookings, participants, families, children and product purchases in Zoho
Confirmation Emails via APIPOST /emailsConfirmation email to the customer
Membership Pass Purchase via APIPOST /membershipsMembership purchase in Zoho and pass balance on the Shopify customer

POST /orders sorts the order's lines by product tag:

Product tagProcessed as
sportA booking, with one participant per line
ecommerce-productA product purchase
NeitherIgnored

The service also reads the order metafield custom.environment and skips any order whose environment is not in its allowed list. An order with no value is treated as production. Nothing in this repository sets that metafield.

Inside Zoho, workflow functions run when the records are created. They calculate family and parent spend, camp booking counts, early bird counts and membership usage. Copies of those functions are in misc/deluge-scripts/, but the live versions are in Zoho.

Emails

shopify-zoho-integration builds every booking email and sends it through Mailgun from ASC-Bookings@australiansportscamps.com.au.

EmailTriggerContent source
Booking confirmationZapier, when the order is createdVariant and product metafields custom.email_template, custom.email_subject, custom.email_templates_what_to_bring, custom.email_templates_pickup_times
7-day reminderDaily scheduled call to POST /emails/cronSame metafields, with custom.email_subject_reminder
2-day reminderSame daily callSame

The service records each email it sends in Firestore, so a repeated trigger does not send a second copy. The schedule itself is configured in Google Cloud, not in any repository.

Early bird dates

Zoho needs to know whether a booking was made at the early bird price. The integration looks up the Early Bird Dates metaobject whose handle is the camp's season in lower case, a hyphen and the year, for example spring-2026. The same lookup runs when camps are uploaded to Zoho and when a camp swap is completed. Create the entry for a season before its camps go on sale. See Pricing and early bird.

Failure modes

SymptomLikely cause
Book Camp button is greyed outVariant sold out, or In Season is false
Booking form does not opencamp-booking.bundle.js failed to load, or the product is not using the theme.product layout
School search shows no resultsGoogle Places key restricted or missing from the build
Club search shows no resultsshopify-zoho-integration unreachable, or the endpoint missing from the build
Order paid but no booking in ZohoZap turned off or errored, the /orders call failed, or the order's environment was skipped
Customer received no confirmation"Confirmation Emails via API" zap, Mailgun, or missing email template metafields
Saved child is missing some detailsKnown issue, see Booking form

Diagnosis steps are in The booking form is not working and A booking is missing in Zoho.

Source map

ConcernLocation
Book Camp button and quantitytheme/snippets/product-atc.liquid, theme/assets/main-product.js
Booking form mount point and configtheme/layout/theme.product.liquid
Booking formsrc/js/camp-booking.js, src/components/CampBooking.tsx, src/components/ParticipantDetails.tsx
Validation rulessrc/components/models/ParticipantDetailsSchema.tsx
Add to cartsrc/components/utils.tsx
Live carttheme/sections/asc-new-cart-layout.liquid, theme/assets/cart-layout.js
Checkout eventtheme/snippets/asc-track-checkout.liquid
Order processing, emailsasc-api-src-zoho-integration repository, src/features/orders.ts, src/features/bookings.ts, src/features/emails.ts

On this page