@firstflow/react 0.0.1 → 0.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -315
- package/dist/chunk-WTTDFCFD.mjs +2157 -0
- package/dist/events-DAiGBrYc.d.mts +325 -0
- package/dist/events-DAiGBrYc.d.ts +325 -0
- package/dist/index.d.mts +356 -395
- package/dist/index.d.ts +356 -395
- package/dist/index.js +4726 -666
- package/dist/index.mjs +3242 -1272
- package/dist/internal.d.mts +131 -0
- package/dist/internal.d.ts +131 -0
- package/dist/internal.js +915 -0
- package/dist/internal.mjs +228 -0
- package/package.json +27 -9
- package/dist/index.css +0 -360
package/README.md
CHANGED
|
@@ -1,315 +1,107 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
##
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
| **`useFeedback()`** (no args) | Programmatic feedback only: `submit(payload)`, `getConfig()`, `isEnabled()` (e.g. custom slots). |
|
|
109
|
-
|
|
110
|
-
#### Headless message ratings: `useFeedback({ ... })`
|
|
111
|
-
|
|
112
|
-
Inside `FirstflowProvider`, pass `conversationId`, `messageId`, and `messagePreview`. Returns `rating`, `selectedTags`, `comment`, `setRating`, `toggleTag`, `setComment`, `submit`, `isEnabled`, `config`, `sideConfig`, plus `submitting`, `submitted`, `error`, `clearError`.
|
|
113
|
-
|
|
114
|
-
```tsx
|
|
115
|
-
import { useFeedback } from '@cdn/react-issue-reporter';
|
|
116
|
-
|
|
117
|
-
function MyFeedbackRow({ conversationId, messageId, preview }: Props) {
|
|
118
|
-
const { rating, setRating, submit, isEnabled, submitting, sideConfig, selectedTags, toggleTag, comment, setComment } =
|
|
119
|
-
useFeedback({
|
|
120
|
-
conversationId,
|
|
121
|
-
messageId,
|
|
122
|
-
messagePreview: preview,
|
|
123
|
-
metadata: { surface: 'chat' },
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
if (!isEnabled) return null;
|
|
127
|
-
|
|
128
|
-
return (
|
|
129
|
-
<div className="flex flex-col gap-2">
|
|
130
|
-
<div className="flex gap-2">
|
|
131
|
-
<button
|
|
132
|
-
type="button"
|
|
133
|
-
className={rating === 'like' ? 'bg-green-600 text-white' : 'bg-gray-200'}
|
|
134
|
-
onClick={() => setRating('like')}
|
|
135
|
-
>
|
|
136
|
-
Helpful
|
|
137
|
-
</button>
|
|
138
|
-
<button
|
|
139
|
-
type="button"
|
|
140
|
-
className={rating === 'dislike' ? 'bg-red-500 text-white' : 'bg-gray-200'}
|
|
141
|
-
onClick={() => setRating('dislike')}
|
|
142
|
-
>
|
|
143
|
-
Not helpful
|
|
144
|
-
</button>
|
|
145
|
-
</div>
|
|
146
|
-
{rating && sideConfig && (
|
|
147
|
-
<>
|
|
148
|
-
<p className="text-xs font-semibold">{sideConfig.heading}</p>
|
|
149
|
-
<div className="flex flex-wrap gap-1">
|
|
150
|
-
{sideConfig.tags.map((tag) => (
|
|
151
|
-
<button key={tag} type="button" onClick={() => toggleTag(tag)} className={selectedTags.includes(tag) ? 'ring-2 ring-blue-500' : ''}>
|
|
152
|
-
{tag}
|
|
153
|
-
</button>
|
|
154
|
-
))}
|
|
155
|
-
</div>
|
|
156
|
-
<textarea value={comment} onChange={(e) => setComment(e.target.value)} placeholder={sideConfig.placeholder} />
|
|
157
|
-
<button type="button" disabled={submitting} onClick={() => void submit()}>
|
|
158
|
-
{submitting ? 'Sending…' : 'Send'}
|
|
159
|
-
</button>
|
|
160
|
-
</>
|
|
161
|
-
)}
|
|
162
|
-
</div>
|
|
163
|
-
);
|
|
164
|
-
}
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
#### Ready component: `MessageFeedback`
|
|
168
|
-
|
|
169
|
-
Use **`MessageFeedback`** when `feedback_config.enabled` is true (from agent or from `createFirstflow({ feedbackConfig })`):
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
// App root: one provider after firstflow is ready
|
|
173
|
-
<FirstflowProvider firstflow={firstflow}>
|
|
174
|
-
<ChatMessage conversationId={cid} messageId={mid} text={assistantText} />
|
|
175
|
-
</FirstflowProvider>
|
|
176
|
-
|
|
177
|
-
function ChatMessage({ conversationId, messageId, text }) {
|
|
178
|
-
return (
|
|
179
|
-
<MessageFeedback
|
|
180
|
-
conversationId={conversationId}
|
|
181
|
-
messageId={messageId}
|
|
182
|
-
messagePreview={text}
|
|
183
|
-
/>
|
|
184
|
-
);
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
- **`variant="default"`** (default): preview box + thumbs + form.
|
|
189
|
-
- **`variant="inline"`**: thumbs only in the first fragment node (place beside the message in a flex row); after the user picks like/dislike, the tag/comment form renders in a second fragment node — use a wrapping flex container with `flex-wrap: wrap` and give the form child `flex: 1 1 100%` so it spans the full width below.
|
|
190
|
-
- **`inlineFormSurface="dark"`**: when using `variant="inline"`, styles the expanded form for dark chat backgrounds.
|
|
191
|
-
|
|
192
|
-
Programmatic (no UI):
|
|
193
|
-
|
|
194
|
-
```ts
|
|
195
|
-
await firstflow.feedback.submit({
|
|
196
|
-
conversationId: 'conv_1',
|
|
197
|
-
messageId: 'msg_assistant_42',
|
|
198
|
-
rating: 'like', // or 'dislike'
|
|
199
|
-
comment: 'optional',
|
|
200
|
-
messagePreview: 'snippet for analytics',
|
|
201
|
-
metadata: { page: '/chat', locale: 'en' },
|
|
202
|
-
});
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
**Jitsu event `feedback_submitted`** — properties (snake_case) include:
|
|
206
|
-
|
|
207
|
-
| Property | Required | Notes |
|
|
208
|
-
|----------|----------|--------|
|
|
209
|
-
| `agent_id` | yes | Injected by SDK |
|
|
210
|
-
| `session_id`, `device_type` | yes | Injected by SDK |
|
|
211
|
-
| `anonymousId` | yes | On envelope (Segment-style) |
|
|
212
|
-
| `conversation_id` | yes | From host |
|
|
213
|
-
| `message_id` | yes | From host |
|
|
214
|
-
| `rating` | yes | `like` \| `dislike` |
|
|
215
|
-
| `comment` | no | Free text |
|
|
216
|
-
| `message_preview` | no | Truncated (~2000 chars) |
|
|
217
|
-
| `metadata` | no | Arbitrary JSON object (serializable keys/values; max ~32KB serialized) |
|
|
218
|
-
| `submitted_at` | yes | ISO timestamp |
|
|
219
|
-
|
|
220
|
-
**Analytics:** “Current” feedback per user per message is the **latest** row by timestamp for the same `message_id` and identity (`anonymousId` / `userId`), e.g. `ROW_NUMBER() OVER (PARTITION BY message_id, anonymous_id ORDER BY timestamp DESC) = 1` in your warehouse.
|
|
221
|
-
|
|
222
|
-
### 5. Experience flow: Message nodes (`useExperienceMessageNode`)
|
|
223
|
-
|
|
224
|
-
Headless hook for a **Message** step in an experience (config matches the dashboard message node: text, carousel, quick replies, CTAs, **`ctaUrl`** / **`ctaPrompt`**). It returns **`blocks`** in fixed order (`text` → `carousel` → `quick_replies` → `cta_primary` → `cta_dismiss`), **`blocksVersion`** (currently **4**; quick-reply options are `{ label, prompt? }` and `quick_reply` actions include optional **`promptText`**; v3 added primary CTA **`promptText`**; v2 added per-card carousel CTA fields), **`ui`** flags, and **`handlers`** for clicks. Integrate navigation in **`onAction`** (map `kind` / `label` / `promptText` / `url` / `index` / `cardId` / `actionId` to your graph — e.g. send **`promptText`** or **`label`** as the user message for button CTAs and quick replies, open **`url`** for link CTAs).
|
|
225
|
-
|
|
226
|
-
| Topic | Behavior |
|
|
227
|
-
|-------|----------|
|
|
228
|
-
| **Shown** | `EXPERIENCE_SHOWN` on mount by default (`trackShownOnMount: true`). |
|
|
229
|
-
| **Dedupe** | Module-scoped Set: same default key (`agentId` + `experienceId` + `nodeId` + `conversationId`) fires **once** per page load. Re-showing the same node in a new run needs a unique **`impressionKey`** (e.g. append `flowInstanceId`) or **`dedupeShown: false`**. |
|
|
230
|
-
| **Virtualized lists** | `trackShownOnMount: false` and call **`reportShown()`** when the row is visible (e.g. IntersectionObserver). |
|
|
231
|
-
| **Clicks** | `EXPERIENCE_CLICKED` with `action` from **`EXPERIENCE_MESSAGE_ANALYTICS_ACTION`** (`cta_primary`, `cta_dismiss`, `quick_reply`, `carousel_cta`). For `cta_primary`, props may include **`cta_url`** (link) and **`cta_prompt`** (button prompt text). For `quick_reply`, props include **`quick_reply_label`**, **`quick_reply_index`**, and optional **`quick_reply_prompt`**. For `carousel_cta`, props include **`card_id`**, **`carousel_action_id`** (`primary` / `secondary`), and when the card is in config: **`carousel_button_action`** (`prompt` / `link`), **`carousel_button_label`**, **`carousel_link_url`**, **`carousel_prompt`**. Use **`buildExperienceCarouselCtaAction(config, cardId, actionId)`** if you build clicks outside **`handlers.onCarouselCta`**. **`message_style`** normalizes legacy `inline` to `message`. |
|
|
232
|
-
| **Errors** | `onAction` / `mapAnalytics` throws are logged; analytics still runs (`onAction` first, then track; if `mapAnalytics` throws, base props are tracked). |
|
|
233
|
-
|
|
234
|
-
Optional **`mapAnalytics(eventName, props)`** transforms payloads before `track` (avoid renaming events unless intentional).
|
|
235
|
-
|
|
236
|
-
**Next step (not in SDK yet):** a thin `<MessageNode />` wrapper around this hook for default markup.
|
|
237
|
-
|
|
238
|
-
### 6. Imperative mount (optional DOM adapter)
|
|
239
|
-
|
|
240
|
-
```ts
|
|
241
|
-
import { createFirstflow, mount } from '@cdn/react-issue-reporter';
|
|
242
|
-
|
|
243
|
-
const firstflow = createFirstflow({ agentId, apiUrl });
|
|
244
|
-
const unmount = mount(firstflow, document.getElementById('issue-root'));
|
|
245
|
-
// Later: firstflow.issue.open() opens the modal.
|
|
246
|
-
// Teardown: unmount(); firstflow.issue.destroy();
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
## API
|
|
250
|
-
|
|
251
|
-
### createFirstflow(options)
|
|
252
|
-
|
|
253
|
-
Returns a **FirstflowInstance** (root platform context).
|
|
254
|
-
|
|
255
|
-
- `options.agentId` (string)
|
|
256
|
-
- `options.apiUrl` (string)
|
|
257
|
-
- `options.jitsuHost?` (string) — Jitsu host for analytics; defaults to shared Firstflow Jitsu if omitted
|
|
258
|
-
- `options.jitsuWriteKey?` (string) — Jitsu write key; defaults to shared key if omitted
|
|
259
|
-
|
|
260
|
-
**FirstflowInstance:**
|
|
261
|
-
|
|
262
|
-
- `agentId`, `apiUrl` (read-only)
|
|
263
|
-
- `analytics` — platform analytics API (used by all feature modules):
|
|
264
|
-
- `track(eventName, properties?)` — send a track event to Jitsu (Segment-compatible)
|
|
265
|
-
- `identify(userId?, traits?)` — identify a user (optional)
|
|
266
|
-
- `page(name?, properties?)` — page view (optional)
|
|
267
|
-
- `issue` — public issue module API:
|
|
268
|
-
- `open(options?)` — open the issue UI (modal or inline depending on integration)
|
|
269
|
-
- `submit(data)` — submit an issue (form values + optional context)
|
|
270
|
-
- `getConfig()` — read-only config (enabled, promptText, fields)
|
|
271
|
-
- `destroy()` — tear down handlers
|
|
272
|
-
- `feedback` — message feedback (Jitsu `feedback_submitted`):
|
|
273
|
-
- `submit({ conversationId, messageId, rating, comment?, messagePreview?, metadata? })` — tag pills in the UI are not sent to Jitsu; put anything you need for analytics in `metadata`
|
|
274
|
-
- `getConfig()`, `isEnabled()`
|
|
275
|
-
|
|
276
|
-
Naming: issue uses **open** + **submit**; feedback uses **submit** (and optional **MessageFeedback** UI).
|
|
277
|
-
|
|
278
|
-
### React exports
|
|
279
|
-
|
|
280
|
-
- **FirstflowProvider** — accepts `firstflow: FirstflowInstance`; provides the platform instance to the tree. Transitional: it delegates to the existing issue provider; the final architecture may use a single provider for multiple modules.
|
|
281
|
-
- **useFirstflow()** — returns the platform instance from context.
|
|
282
|
-
- **useCreateFirstflow(agentId, apiUrl, { fetchConfig? })** — returns `{ firstflow, loading, error }`. With `fetchConfig: true`, loads `issues_config` and `feedback_config` from the agent on `GET .../config` (supports `{ meta, data: { agent } }`).
|
|
283
|
-
- **useFeedback()** — returns `firstflow.feedback` (must be inside `FirstflowProvider`).
|
|
284
|
-
- **MessageFeedback** — props: `conversationId`, `messageId`, `messagePreview`, optional `metadata`; renders nothing when feedback is disabled.
|
|
285
|
-
- **fetchSdkAgentConfig(apiUrl, agentId)** — low-level fetch of `{ issues_config, feedback_config }`.
|
|
286
|
-
- **useIssueReporter()** — returns `{ reporter, open, reportIssue, submit, config, isModalOpen, closeModal }` for issue-specific state.
|
|
287
|
-
- **InlineIssueForm** — renders the form inline (only when `config.enabled`).
|
|
288
|
-
- **IssueModal** — modal wrapper (rendered by the provider).
|
|
289
|
-
- **FormEngine** — headless-friendly form (config + onSubmit + optional onCancel).
|
|
290
|
-
|
|
291
|
-
### mount(firstflow, target)
|
|
292
|
-
|
|
293
|
-
DOM adapter only: renders `FirstflowProvider` + `InlineIssueForm` into `target` with React 18 `createRoot`. Returns an unmount function.
|
|
294
|
-
|
|
295
|
-
## Issue types (platform-first exports)
|
|
296
|
-
|
|
297
|
-
Issue-specific types are under the **Issue** namespace so the root package stays platform-first:
|
|
298
|
-
|
|
299
|
-
- `Issue.FormValues`, `Issue.ContextMetadata`, `Issue.Payload`, `Issue.OpenOptions`
|
|
300
|
-
- `Issue.NormalizedConfig`, `Issue.NormalizedFieldConfig`, `Issue.RawIssueFieldConfig`, `Issue.RawIssuesConfig`, `Issue.ValidationResult`
|
|
301
|
-
|
|
302
|
-
Platform types at root: `FirstflowInstance`, `CreateFirstflowOptions`, `IssueModulePublic`, `AnalyticsModulePublic`. Event names: `ISSUE_SUBMITTED`, `FEEDBACK_SUBMITTED`, `SURVEY_COMPLETED`, etc. (see `analytics/events`).
|
|
303
|
-
|
|
304
|
-
## Analytics and validation
|
|
305
|
-
|
|
306
|
-
- **Analytics:** Issue submissions (and future modules) go through the platform analytics layer. Feature modules call `firstflow.analytics.track(eventName, properties)`; the analytics service sends Segment-compatible events to Jitsu. See [ANALYTICS.md](./ANALYTICS.md).
|
|
307
|
-
- **Validation:** `validatePayload(data, fields)` applies to form field keys only; used by the issue module before calling `analytics.track("issue_submitted", payload)`.
|
|
308
|
-
|
|
309
|
-
## Architecture
|
|
310
|
-
|
|
311
|
-
See [ARCHITECTURE.md](./ARCHITECTURE.md) for the platform instance, analytics layer, transitional provider design, and data flow.
|
|
312
|
-
|
|
313
|
-
## License
|
|
314
|
-
|
|
315
|
-
Private / Firstflow.
|
|
1
|
+
# Firstflow React SDK
|
|
2
|
+
|
|
3
|
+
Official React SDK for [Firstflow](https://firstflow.app) — in-chat surveys, onboarding flows, announcements, and analytics inside your agent product.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @firstflow/react
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
**Requirements:** React 18+ and React DOM 18+ (peer dependencies).
|
|
12
|
+
|
|
13
|
+
Styles for bundled UI ship with the package and are applied automatically in the browser; you do not need a separate CSS import for default integrations.
|
|
14
|
+
|
|
15
|
+
## Getting started
|
|
16
|
+
|
|
17
|
+
Wrap your app (or chat surface) with `FirstflowProvider`, pass your **agent ID** and **API key** from the Firstflow dashboard, then use hooks and components as needed.
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import {
|
|
21
|
+
FirstflowProvider,
|
|
22
|
+
FirstflowWidget,
|
|
23
|
+
useFirstflow,
|
|
24
|
+
} from "@firstflow/react";
|
|
25
|
+
|
|
26
|
+
export function App() {
|
|
27
|
+
return (
|
|
28
|
+
<FirstflowProvider
|
|
29
|
+
agentId={process.env.NEXT_PUBLIC_FIRSTFLOW_AGENT_ID!}
|
|
30
|
+
apiKey={process.env.NEXT_PUBLIC_FIRSTFLOW_API_KEY!}
|
|
31
|
+
fallback={<span>Loading…</span>}
|
|
32
|
+
onError={(err) => console.error(err)}
|
|
33
|
+
>
|
|
34
|
+
<ChatShell />
|
|
35
|
+
</FirstflowProvider>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ChatShell() {
|
|
40
|
+
const firstflow = useFirstflow();
|
|
41
|
+
firstflow.analytics.track("custom_event", { source: "chat" });
|
|
42
|
+
return <FirstflowWidget />;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Provider
|
|
47
|
+
|
|
48
|
+
- Loads agent configuration from the Firstflow API when `apiKey` is set.
|
|
49
|
+
- Optional `initialSdkPayload` for SSR or bootstrap (same shape as the config API response).
|
|
50
|
+
- Optional `user` (`UserContext`) for identity, traits, and audience targeting.
|
|
51
|
+
- `autoFetchAudienceMembership` defaults to `true`; set `false` if you only use `setAudienceMembership` for segments.
|
|
52
|
+
|
|
53
|
+
## Documentation
|
|
54
|
+
|
|
55
|
+
- **[Product docs](https://firstflow.app)** — guides and dashboard.
|
|
56
|
+
- In this repository: [ARCHITECTURE.md](./ARCHITECTURE.md) (runtime, provider, audience) and [ANALYTICS.md](./ANALYTICS.md) (events, identity, pipeline).
|
|
57
|
+
|
|
58
|
+
## API overview
|
|
59
|
+
|
|
60
|
+
| Area | Main exports |
|
|
61
|
+
|------|----------------|
|
|
62
|
+
| Setup | `FirstflowProvider`, `useFirstflow`, `useFirstflowSelector`, `createFirstflow`, `fetchSdkAgentConfig`, `FIRSTFLOW_PUBLIC_API_BASE_URL` |
|
|
63
|
+
| Surveys | `useFirstflowSurvey`, `Survey` |
|
|
64
|
+
| Experiences | `FirstflowWidget`, `ExperienceSlot`, message/announcement components and hooks (`useExperienceMessageNode`, `useExperienceAnnouncementNode`, eligibility helpers, …) |
|
|
65
|
+
| Types | `FirstflowInstance`, `CreateFirstflowOptions`, `UserContext`, `SdkAgentConfigPayload`, … |
|
|
66
|
+
|
|
67
|
+
Analytics event name constants (stable strings for pipelines): `SURVEY_COMPLETED`, `EXPERIENCE_SHOWN`, `EXPERIENCE_CLICKED`, `CHAT_MESSAGE_SENT`, `EXPERIENCE_ANALYTICS_TYPE`.
|
|
68
|
+
|
|
69
|
+
### Advanced: imperative instance
|
|
70
|
+
|
|
71
|
+
For tests, non-UI tooling, or custom wiring:
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { createFirstflow } from "@firstflow/react";
|
|
75
|
+
|
|
76
|
+
const firstflow = createFirstflow({
|
|
77
|
+
agentId: "...",
|
|
78
|
+
apiKey: "...",
|
|
79
|
+
user: { id: "u1", traits: { plan: "pro" } },
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
await firstflow.refreshConfig();
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Public TypeScript types on `FirstflowInstance` currently emphasize `analytics` and `survey`. Issue reporting and per-message feedback modules are implemented but not exported from the main entry; Firstflow-internal tooling may import `@firstflow/react/internal` until those APIs are published on the default export.
|
|
86
|
+
|
|
87
|
+
### `FirstflowInstance` (public surface)
|
|
88
|
+
|
|
89
|
+
| Member | Purpose |
|
|
90
|
+
|--------|---------|
|
|
91
|
+
| `agentId`, `apiUrl` | Agent identity; API base is defined by the SDK. |
|
|
92
|
+
| `analytics` | `track`, `identify`, `page`. |
|
|
93
|
+
| `survey` | Load and submit survey experiences. |
|
|
94
|
+
| `getUser` / `setUser` | User context and traits. |
|
|
95
|
+
| `setAudienceMembership` / `getAudienceMembership` | Segment membership (`true` only grants a segment). |
|
|
96
|
+
| `getWidgetUi` | Brand hints from agent config. |
|
|
97
|
+
| `refreshConfig`, `reset` | Reload remote config or reset runtime state. |
|
|
98
|
+
|
|
99
|
+
## Best practices
|
|
100
|
+
|
|
101
|
+
- Send product analytics through `firstflow.analytics.track` rather than parallel collectors inside Firstflow flows.
|
|
102
|
+
- After a successful server fetch, audience membership is replaced (not merged); see ARCHITECTURE.md for details.
|
|
103
|
+
- If your CSP blocks inline styles, plan a custom styling strategy; default embeds rely on injected styles from the bundle.
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
See `package.json`. This package is `UNLICENSED` unless your agreement with Firstflow states otherwise.
|