registerDefaultHooks
Registers the engine's built-in slot handlers (GTM, bundles, store closed, fast checkout, price quote, pre-order); importing the hooks module already runs it.
import { registerDefaultHooks } from '@salla.sa/twilight-theme-engine/hooks';In plain words
The engine fills a few slots for you: the Google Tag Manager container, Salla's bundles script, a "store closed" notice, the quick-checkout script, a price-quote button and a pre-order notice. Each one checks the store settings when it renders, and renders nothing when its feature is off.
You never call this function. The first time anything imports @salla.sa/twilight-theme-engine/hooks, it runs by itself, and TwilightProvider imports that module. It is exported so you can see what is there.
Signature
function registerDefaultHooks(): void // What it registers (priority, and when the handler renders something): // body:start GoogleTagBody 100 store.settings.keys.gtm has ids // SiftSnippet 90 store.settings.keys.sift // StoreClosedNotification 80 store.settings.opening_hours.enabled // body:end TwilightBundles 100 always // fast-checkout <script> 90 store.settings.buy_now // cart:submit.start PriceQuoteButton 100 store.settings.features.price_quote // cart:items.start PreOrderNotification 100 features['pre-order-campaigns'] and a // top-level cart item with has_pre_order_campaign
Try it live
| hookRegistry.list() | priorities |
|---|---|
body:start | 100, 90, 80 |
body:end | 100, 90 |
cart:submit.start | 100 |
cart:items.start | 100 |
This store: keys.gtm ["GTM-TGFC6FV"] · buy_now {"label":"Salla","countryCode":"SA","supportedCountries":["SA","BH","KW","OM","QA","AE","JO"],"supportedNetworks":["masterCard","visa"],"validateUri":"/dev-vgckq3fssfhjewwi/checkout/applepay/validate","myfatoorahS2s":false,"currency":"SAR","networks":["masterCard","visa"],"countries":["SA","BH","KW","OM","QA","AE","JO"],"is_digital":false,"merchant_identifier":"salla-internal.salla.sa"}
import { hookRegistry, HookName } from '@salla.sa/twilight-theme-engine/hooks';
// Importing the hooks module already registered the defaults. Never call registerDefaultHooks() again.
// Add your own content next to them:
hookRegistry.register(HookName.BODY_END, () => <div id="chat-widget" />, 10);
Example
import { hookRegistry, HookName } from '@salla.sa/twilight-theme-engine/hooks';
// The defaults are already registered. Add yours next to them:
// a lower priority renders after them.
hookRegistry.register(HookName.BODY_END, () => <div id="theme-chat-root" />, 10);
// Inspect what is there, highest priority first:
hookRegistry.getHandlers(HookName.BODY_START).map((handler) => handler.priority); // [100, 90, 80]
How it behaves
packages/theme-engine/src/hooks/index.tsimports./registerDefaultHooksfor its side effect.TwilightProviderimportsMasterLayout, which imports that barrel, so every theme gets the defaults even if it only imports hook subpaths.The handler components are
React.lazywith aSuspensefallback ofnull: their code downloads only when a handler actually renders something.The Sift handler calls
useUser()inside the handler, which works becauseHookSlotrenders each handler as its own component.The fast-checkout handler keeps
#fast-checkout-jsin the body: TanStack removes head scripts after hydration, andsalla-add-product-buttonlooks the script up by id when it renders.docs/06-hook-system.md, "Auto-Registered Defaults", lists only the first four; the fast-checkout, price-quote and pre-order handlers were added later.
Gotchas
Calling it again registers every default a second time (the registry never de-duplicates), duplicating GTM, the bundles script and the checkout script.
hookRegistry.clear(HookName.BODY_START)orBODY_END, and unmounting anyuseHookon those names, removes these defaults along with everything else there.<TwilightProvider gtm={false}>(packages/theme-engine/docs/gtm-integration.md, "Disable Automatic GTM") does not stop the GTM container: the prop is declared but nothing reads it. There is no way to remove only the GTM default; clearingbody:startalso removes the Sift and store-closed handlers.keys.sift,opening_hoursandfeaturesare marked "TODO: add to API response" in theStoreSettingstype, so those defaults may never render with real store data. This demo store has noopening_hourstoday.
Related
The one shared list of slot handlers: register content under a slot name, read or clear it, or register many at once with defineHooks.
HookNameThe predefined slot names as a TypeScript enum, so a typo fails to compile instead of silently filling a slot nobody renders.
useGtmPushes ecommerce events (view, impressions, click, add to cart, checkout, purchase) to Google Tag Manager's dataLayer when the store has GTM.
useOpeningHoursWorks out from a weekly schedule whether the store is open right now and, when closed, when it opens next.