# Kibble installation contract: section 6 of 29 (guide version 3)

> This is **one section only**, not the whole contract. Complete document: https://www.usekibble.dev/AI/guide.md

## 6. Decide what to install {#decide}

### Where the SDK is installed (exactly one)

- You can edit the site’s code: install the [snippet](https://www.usekibble.dev/AI#snippet) in the shared layout ([Next.js](https://www.usekibble.dev/AI#nextjs), [WordPress](https://www.usekibble.dev/AI#wordpress), plain HTML).
- You can only use a tag manager: use the [GTM](https://www.usekibble.dev/AI#gtm) Custom HTML tag. If the code already has the snippet, do not add a tag.
- Shopify checkout or BigCommerce storefront: the platform recipe ([Shopify](https://www.usekibble.dev/AI#shopify), [BigCommerce](https://www.usekibble.dev/AI#bigcommerce)) for the pages the platform renders.
- A strict CSP or a requirement to keep requests first-party: a [first-party gateway](https://www.usekibble.dev/AI#gateways), with `data-endpoint` set to it.

### Then, for each capability

| If the site… | Do this | Never |
| --- | --- | --- |
| has a consent banner or CMP | Call `kibble('consent', …)` from the real analytics choice and re-apply it on every load, or use `data-consent="google-consent-mode"` when Consent Mode already carries the choice | pre-grant, map advertising consent, or treat "implied" consent as granted without the owner’s decision |
| is a single-page app with history routing | Nothing: page views are automatic | add your own page-view calls |
| uses hash routing (`/#/path`) | Report it: hash routes are not tracked as page views | emulate page views with `track('page_view')` on hash changes without the owner’s agreement (it is not a supported pattern) |
| has forms people complete | Mark them with `data-kibble-form` and a type; call `formAccepted` in the server-accepted branch ([Forms](https://www.usekibble.dev/AI#forms)) | read or send field values; call `formAccepted` on submit; add a hook for Contact Form 7 |
| has a genuine site search | Call `search()` once per search with the real result count ([Site search](https://www.usekibble.dev/AI#search)) | invent a search, send a booking widget as search, or send 0 when the count is unknown |
| has a booking widget on the website | Mark its business-id and stay fields with `data-kibble-criteria` ([Booking](https://www.usekibble.dev/AI#booking)) | send `availability` from the widget, or mark promo, name or free-text fields |
| hands off to a booking engine you can instrument | Push `availability_search` (a golf course: `tee_time_search` and `tee_time_selected`), `booking_step` and `booking_confirmed` with a reference from the engine; register the engine host as an external connection (with its tenant when the host is shared) | confirm a booking on submit or from a URL |
| sells online | Use the existing GA4 dataLayer events with `data-datalayer="on"`, or the platform recipe | send the same step from both GTM and code |
| has a confirmed outcome without a reference | Leave it as an outcome candidate and report it; staff decide | fabricate a reference or emit an outcome anyway |
| has hotels, destinations, rooms or products with ids | Generate the [site manifest](https://www.usekibble.dev/AI#site-catalog) from the authoritative source and, if the site can host it, publish it at `/kibble/site.json` ([Manifest](https://www.usekibble.dev/AI#manifest)) | guess names or ids, or put anything private in it |
| needs something listed as not implemented | Record it as "not implemented in Kibble" | build a workaround that sends unsupported data |

### Write the plan before you change code

List each row of the [capability matrix](https://www.usekibble.dev/AI#capabilities) as applicable or not applicable, with the reason and the exact interface you will use. Share it with the person if anything is ambiguous (consent category, which response proves acceptance, which field is a business id). Everything you implement must appear in the plan; everything in the plan must appear in the report.

END OF SECTION decide
