@evaro/connect-react
v0.2.0
Published
Native React integration for Evaro Connect. Drop-in component and hooks for B2B partners (Patient.info, future React vendors).
Readme
@evaro/connect-react
Native React integration for Evaro Connect. Drop this into any React 18 or 19 app and replace manual window.evaro_connect(...) snippets with idiomatic components and hooks. Designed for B2B partners like Patient.info who want a maintainable, type-safe integration that scales across many pages.
Install
pnpm add @evaro/connect-react
# or
npm install @evaro/connect-reactPeer dependencies: react >= 18, react-dom >= 18.
Quick start
Embed a landing page
Render a full Evaro landing (hero, FAQ, etc.) with a single component — no provider, no URLs:
import { EvaroLanding } from '@evaro/connect-react'
<EvaroLanding vendor="03f0db937fd156141d272250a2b59f" template="erectile-dysfunction" />It fetches the prerendered landing and renders it inside a Shadow DOM, so your React tree and CSS stay untouched. The CDN and analytics URLs resolve automatically — see Environments.
Add launcher buttons
For call-to-action buttons that open Connect, wrap your app once with <EvaroProvider> and map your conditions:
import { EvaroProvider } from '@evaro/connect-react'
const conditions = {
'erectile-dysfunction': '93e6e49e13c458706634eecd58423a',
'migraine-relief': '4f4ce914783df03cc18e793cb8bff0',
'weight-loss': '70198fea75871263274d8a554ed584',
}
export default function App({ children }) {
return (
<EvaroProvider vendorHash="03f0db937fd156141d272250a2b59f" conditions={conditions}>
{children}
</EvaroProvider>
)
}Then drop the launcher anywhere you want a call-to-action:
import { EvaroConnect } from '@evaro/connect-react'
<EvaroConnect condition="migraine-relief" className="cta-button">
Start free consultation
</EvaroConnect>Connect's iframe.js loads lazily on first click — your page bundle stays small. The provider is optional: it lets every nested <EvaroLanding> / <EvaroConnect> share one vendorHash (and env) instead of repeating them, and it's what resolves <EvaroConnect condition="…">.
Environments
You never paste a URL. The package resolves Evaro's CDN and API automatically — production by default. An Evaro-internal app with dev/staging deploys passes a single env:
<EvaroLanding vendor="…" template="…" env="dev" /> // standalone
<EvaroProvider vendorHash="…" env="dev">…</EvaroProvider> // or once, inheritedenv accepts dev / staging / prod, plus the aliases development / production and preview (→ staging) — so you can pass VERCEL_ENV straight through. One env resolves the landings CDN, the analytics API and the Connect launcher together. Omit it and you get production. Third-party vendors never set it.
<EvaroProvider> props
| Prop | Type | Notes |
|---|---|---|
| vendorHash | string (required) | Your Evaro vendor hash (32 hex). One value per app. |
| conditions | Record<string, string \| ConditionMapping> | Optional. Lookup table for <EvaroConnect condition="...">. Values can be a bare questionnaire hash, a full link (vendorHash/questionnaire/qHash), or an object with questionnaireId, productId, or link. |
| env | 'dev' \| 'staging' \| 'prod' | Optional. Evaro environment; resolves the CDN + API URLs. Default prod. Inherited by nested components. |
| apiBase | string | Optional. Explicit API base URL — advanced override, prefer env. |
<EvaroConnect> props
| Prop | Type | Notes |
|---|---|---|
| link | string | Direct link, e.g. abc/product/p1. Takes precedence over category and condition. |
| condition | string | Looks up the link from <EvaroProvider conditions={...}>. |
| vendor | string | Vendor hash. Required for category; otherwise inherited from <EvaroProvider>. |
| category | string | Category slug, resolved against the vendor's Evaro-hosted category map. A category Evaro has not published renders nothing — no error. |
| cdn | string | Explicit CDN origin for the category map. Advanced override — prefer env. |
| patient | { state?: object } | Prefill data merged into Connect's localStorage before opening. |
| env | 'dev' \| 'staging' \| 'prod' | Optional. Connect environment. Inherited from <EvaroProvider>; default prod. See Environments. |
| disabled | boolean | Standard disabled behavior. |
| as | (props) => ReactNode | Render-prop override. Use to render an <a>, custom component, etc. |
| onOpen | (link, event) => void \| boolean \| Promise<...> | Called before the open. Return false (or resolve to false) to cancel. |
| onError | (err: Error) => void | Called when the lazy-load or open fails. |
All standard <button> attributes pass through.
Bulk configuration across many pages
Define your full conditions table once, then reference by key everywhere:
<EvaroConnect condition="migraine-relief" /> // resolves to .../questionnaire/4f4ce91...
<EvaroConnect condition="weight-loss" /> // resolves to .../questionnaire/70198fe...
<EvaroConnect link="abc/product/63ed362..." /> // direct override, ignores conditionsUpdates to the questionnaire mapping happen in one file. No per-page edits.
Analytics
The Evaro API is the source of truth for analytics config. On mount, the SDK loads /json/api/v1/vendor/{vendor}/gtm-snippet and /json/api/v1/vendor/{vendor}/event-handler from the API. Both endpoints return empty strings when the vendor has no google_tag_manager_id configured, so the bootstrap is safe regardless. No GTM ID prop on the vendor side.
If your site has its own GTM container, it sits alongside Evaro's on the same window.dataLayer. Evaro event names are namespaced (page_view_dlv, the Evaro ecommerce names) so your container can filter them with exclusion rules if needed.
If you want to forward Evaro events to a different analytics system, use useEvaroAnalytics() to subscribe to the raw EVARO_ANALYTIC_EVENT window event directly.
Hooks
useEvaroAnalytics(handler)
Subscribe to Connect's analytics events. The handler fires for every EVARO_ANALYTIC_EVENT dispatched by the iframe. Event names follow the contract: evaro_page_view, evaro_app_closed, evaro_purchase, evaro_add_to_cart, evaro_remove_from_cart, evaro_view_cart, evaro_begin_checkout, evaro_product_choice.
useEvaroAnalytics(({ event, data }) => {
if (event === 'evaro_purchase') {
yourAnalytics.track('partner.conversion', data)
}
})useEvaroState()
Reads window.evaro_state and subscribes to updates. Returns { cart, user } derived from Connect's localStorage.
const { cart, user } = useEvaroState()
return user ? <span>Welcome, {user.email}</span> : <SignIn /><EvaroLanding> — full landing page
Renders an Evaro-built landing page (hero, FAQ, etc.) inside a Shadow DOM, so your React tree and CSS stay untouched. Works with or without <EvaroProvider>.
// standalone — pass the vendor hash directly:
<EvaroLanding vendor="03f0db937fd156141d272250a2b59f" template="patient-info" category="erectile-dysfunction" />
// inside a provider — vendor (and env) are inherited:
<EvaroLanding template="patient-info" category="erectile-dysfunction" />One template can be reused across many categories: pass a fixed template and vary category, and Evaro serves that category's content and CTA. Switching category swaps the whole page from a single component.
| Prop | Type | Notes |
|---|---|---|
| template | string (required) | Landing template slug. |
| vendor | string | Vendor hash. Required unless inherited from <EvaroProvider>. |
| category | string | Optional. Category slug. Selects which consultation the CTA opens — and, for a category-driven template, which content Evaro renders. A category Evaro has not published renders nothing. |
| env | 'dev' \| 'staging' \| 'prod' | Optional. See Environments. Inherited from the provider; default prod. |
| cdn / apiBase | string | Optional explicit URL overrides — advanced, prefer env. |
| onReady / onLoadError | () => void / (err) => void | Manifest fetch lifecycle callbacks. |
Server-side rendering
Components and hooks are SSR-safe — they no-op on the server and hydrate on mount. Connect's iframe.js only loads when a user interacts.
TypeScript
Full types are exported. See dist/index.d.ts after install.
Migration from the Phase 1 manual snippet
Replace:
<script src="https://connect.evaro.com/iframe.js" defer></script>
<script src="https://api.evaro.com/json/api/v1/vendor/{hash}/gtm-snippet"></script>
<script src="https://api.evaro.com/json/api/v1/vendor/{hash}/event-handler" defer></script>
<button onclick="window.evaro_connect('{vendorHash}/questionnaire/{qHash}')">
Start free consultation
</button>with:
import { EvaroProvider, EvaroConnect } from '@evaro/connect-react'
<EvaroProvider
vendorHash="{vendorHash}"
conditions={{ migraine: '{qHash}' }}
>
...
<EvaroConnect condition="migraine">Start free consultation</EvaroConnect>
</EvaroProvider>The package handles iframe.js loading, GTM bootstrap, and the analytics bridge. No manual script tags.
