Integrations and analytics
Mandatory headless global host, once directly inside PandaProvider next to PandaAnalytics.
Anatomy
Every piece of Integrations and analytics as it nests in code. A root holds the data and state; its parts and hooks only work inside it.
<PandaProvider>Mounted once in app/layout.tsx<PandaIntegrations />complete widgetMandatory headless global host, once directly inside PandaProvider next to PandaAnalytics.
<PandaIntegrationPlacement />complete widgetHeadless WhatsApp/Telegram binding.
<PandaIntegration />complete widgetHeadless binding to an AI-declared integration of any kind: content, contact menu, popup, embed or custom SDK.
<PandaAnalytics />complete widgetPanda site analytics, shown in the owner's dashboard (Analytics): a page_view on load and on every client navigation (pathname change, via…
</PandaProvider>Installation
- 1npm install <tarball or @pandaidx/widgets>Terminalnpm install https://github.com/pandaidx/panda-widgets/releases/download/v1.14.1/pandaidx-widgets-1.14.1.tgz
- 2import "@pandaidx/widgets/styles.css" in app/layout.tsx
- 3Wrap the site in <PandaProvider publicKey apiUrl preset theme> (app/layout.tsx)
- 4In each page (Server Component) call the widget's server loader, then render the widget with its data
- 5Allow the images: next.config images.remotePatterns [{ protocol: "https", hostname: "**" }] (listing and blog photos come from several CDNs)
Usage
import { fetchSiteRuntime } from "@pandaidx/widgets/server"import { PandaProvider, PandaIntegrations, PandaAnalytics } from "@pandaidx/widgets/client"const runtime = await fetchSiteRuntime({ publicKey, apiUrl, locale })<PandaProvider publicKey={publicKey} locale={locale}><PandaIntegrations initialData={runtime ?? undefined} /><PandaAnalytics />{children}</PandaProvider>
API reference
PandaIntegrations
Mandatory headless global host, once directly inside PandaProvider next to PandaAnalytics. Declare site integrations and their public variables with site_integrations. Read live variables with usePandaSiteIntegration(id), or PandaIntegration with any authored component, menu, popup or script. An optional provider recipe executes once here; custom code owns its own lifecycle. The CMS lists only declared integrations. Provider scripts are suppressed in previews. Providers without teardown reload once after configuration changes.
Import from @pandaidx/widgets/client · renders inside PandaProvider
| Prop | Type | Default | Description |
|---|---|---|---|
| initialData | object | — | Optional fetchSiteRuntime result for the initial render; refreshed automatically. |
PandaIntegrationPlacement
Headless WhatsApp/Telegram binding. Renders your children only while the CMS integration is enabled. No button, dialog, positioning or styling is imposed; existing design fields are optional hints for the authored component.
Import from @pandaidx/widgets/client · renders inside PandaProvider
| Prop | Type | Default | Description |
|---|---|---|---|
| integration* | string | — | whatsapp or telegram |
| placementId* | string | — | Stable unique position in the page |
| initialData | object | — | Optional live runtime bootstrap from fetchSiteRuntime. |
| children* | function | — | Receives typed connection data, enabled, config, design hints and href; returns any authored UI. |
PandaIntegration
Headless binding to an AI-declared integration of any kind: content, contact menu, popup, embed or custom SDK. Declare its id/title/public variables and named page instances with site_integrations (panda-integrations skill). The CMS shows only declared cards. Children own all design and behavior. Disabled or retired returns nothing. Alternatively use usePandaSiteIntegration(id, undefined, instanceId), honor enabled and put data-panda-integration=id plus data-panda-integration-instance on your actual component and portal content. A capture.exclude declaration applies data-panda-screenshot-exclude=true to this wrapper; mark separately portaled overlays explicitly.
Import from @pandaidx/widgets/client · renders inside PandaProvider
| Prop | Type | Default | Description |
|---|---|---|---|
| id* | string | — | Stable declared integration id, e.g. contact-menu. |
| instanceId | string | — | Stable declared page instance id. Required when the declaration lists instances; omitted for compatible global legacy declarations. |
| initialData | object | — | Optional live runtime bootstrap from fetchSiteRuntime. |
| children* | function | — | Receives title, enabled and live values; returns arbitrary authored UI. |
PandaAnalytics
Panda site analytics, shown in the owner's dashboard (Analytics): a page_view on load and on every client navigation (pathname change, via usePathname), with UTM parameters and the landing referrer; listing_view when a listing detail opens; likes, saved searches and collection adds of signed-in visitors (property_like, property_unlike, property_save_search, property_collection_add); and custom snake_case events from usePandaTrack() or window.panda.track(name, data) (data: up to 20 primitive values). Form submissions (form_submission) and sign-ups (signup) are recorded by Panda server-side and attributed to the same visitor. Visitor id (localStorage) and a 30-minute rolling session are kept on the site's origin. Nothing is recorded when the owner has Analytics off, for signed-in visitors' page views, or from AI Builder previews and localhost. Mount it ONCE in app/layout.tsx inside <PandaProvider>; it renders nothing. Mandatory on AI Builder sites (managed layout).
Import from @pandaidx/widgets/client · renders inside PandaProvider
No props.
Server data
Loaders run in a Server Component and come from @pandaidx/widgets/server. Typed data is for a page you design yourself, rendered inside the root.
fetchSiteRuntime()widget loaderRead live runtime settings without caching. Pass the visitor locale used by PandaProvider; omit it for the source-language fallback. Returns SiteRuntime | null