face-age 2.3.13 → 2.4.2

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 CHANGED
@@ -1,482 +1,469 @@
1
- <br />
1
+ # Face Age — AI Skin Analysis SDK
2
+
3
+ **AI-powered JavaScript SDK for skin analysis, face scanning, and beauty tech applications.**
4
+
5
+ Detect skin age, wrinkles, acne, dark circles, pores, pigmentation, oiliness, and more — then deliver personalized skincare product recommendations and routines, all embedded directly in your website or app.
2
6
 
3
7
  <p align="center"><img src="https://static.getfaceage.com/logo.png" width="232px"></p>
4
8
 
5
9
  <p align="center">
6
- <a href="https://demo.getfaceage.com" target="_blank" rel="noopener noreferrer">Demo</a> /
7
- <a href="https://panel.getfaceage.com" target="_blank" rel="noopener noreferrer">Get Face Age ID</a>
10
+ <a href="https://www.npmjs.com/package/face-age"><img src="https://img.shields.io/npm/v/face-age.svg" alt="npm version" /></a>
11
+ <a href="https://www.npmjs.com/package/face-age"><img src="https://img.shields.io/npm/dm/face-age.svg" alt="npm downloads" /></a>
12
+ <a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT license" /></a>
8
13
  </p>
9
14
 
10
- <br />
11
-
12
15
  <p align="center">
13
- A modern JavaScript library for skin beauty and healthcare, enabling the creation of interactive data visualizations with a simple-to-use API. The platform provides customized skincare solutions through precise skin analysis and is suitable for both commercial and non-commercial projects.
16
+ <a href="https://demo.getfaceage.com" target="_blank" rel="noopener noreferrer">Live Demo</a> ·
17
+ <a href="https://panel.getfaceage.com" target="_blank" rel="noopener noreferrer">Get Your API Key</a> ·
18
+ <a href="https://getfaceage.com/" target="_blank" rel="noopener noreferrer">Website</a>
14
19
  </p>
15
20
 
16
- <br />
17
-
18
21
  <p align="center">
19
22
  <a href="https://getfaceage.com/">
20
23
  <img src="https://static.getfaceage.com/v2.0/preview.png" />
21
24
  </a>
22
25
  </p>
23
26
 
24
- <br />
27
+ ---
28
+
29
+ ## Table of Contents
30
+
31
+ - [Features](#features)
32
+ - [How It Works](#how-it-works)
33
+ - [Installation](#installation)
34
+ - [Quick Start](#quick-start)
35
+ - [Configuration Options](#configuration-options)
36
+ - [Analytics Integration](#analytics-integration)
37
+ - [API Reference](#api-reference)
38
+ - [Events](#events)
39
+ - [Contact](#contact)
40
+
41
+ ---
42
+
43
+ ## Features
44
+
45
+ - **AI Skin Analysis** — camera capture or image upload with real-time face detection
46
+ - **13 Skin Metrics** — wrinkles, acne, dark circles, pores, pigment, redness, oiliness, dryness, and more
47
+ - **3 Display Modes** — embed as a widget, inline section, or full-screen modal
48
+ - **Product Recommendations** — show matched products with add-to-cart and checkout callbacks
49
+ - **Skincare Routines** — group recommendations by morning/evening routine steps
50
+ - **Quiz Flow** — collect user preferences with pre-fillable form fields
51
+ - **Analysis History** — persist previous scans via browser storage or your own backend
52
+ - **Discount Banners** — display copyable promo codes in the recommendation flow
53
+ - **PDF Reports** — generate downloadable skin analysis reports (plan-dependent)
54
+ - **Analytics** — built-in Google Analytics (GTM) and Facebook Pixel event tracking
55
+ - **40 Languages** — full RTL support for Arabic, Persian, and Urdu
56
+
57
+ ---
58
+
59
+ ## How It Works
60
+
61
+ 1. **Embed** a `<div>` on your page and initialize `FaceAge` with your license ID
62
+ 2. **User scans** — via camera or image upload; the SDK runs AI analysis in the browser
63
+ 3. **Results display** — skin age, damage score, and detected problems are shown
64
+ 4. **Recommendations** — matched products and routines from your catalog appear automatically
65
+ 5. **Your code reacts** — use the API and event callbacks to connect to your cart, CRM, or analytics
66
+
67
+ You only need a [Face Age Client ID](https://panel.getfaceage.com) to get started.
68
+
69
+ ---
25
70
 
26
- ## Getting Started
71
+ ## Installation
27
72
 
28
- ### Installation
73
+ ### npm / yarn
29
74
 
30
75
  ```bash
31
76
  npm install face-age --save
32
77
  ```
33
78
 
34
- <p>or</p>
35
-
36
79
  ```bash
37
80
  yarn add face-age --save
38
81
  ```
39
82
 
40
- ### Direct `<script>` Inclusion
41
-
42
- <p>You can also directly include the script in your HTML:</p>
83
+ ### CDN (script tag)
43
84
 
44
- ```bash
85
+ ```html
45
86
  <script src="https://cdn.jsdelivr.net/npm/face-age"></script>
46
87
  ```
47
88
 
89
+ ### Framework Wrappers
48
90
 
49
- ## Wrappers for React/Vue
50
-
51
- Integrate easily with 3rd party frameworks
91
+ Pre-built wrappers are available for component-based frameworks:
52
92
 
53
- - [react-face-age](https://www.npmjs.com/package/react-face-age)
54
- - [vue-face-age](https://www.npmjs.com/package/vue-face-age)
55
- - [vue3-face-age](https://www.npmjs.com/package/vue3-face-age)
93
+ | Framework | Package |
94
+ |-----------|---------|
95
+ | React | [react-face-age](https://www.npmjs.com/package/react-face-age) |
96
+ | Vue 2 | [vue-face-age](https://www.npmjs.com/package/vue-face-age) |
97
+ | Vue 3 | [vue3-face-age](https://www.npmjs.com/package/vue3-face-age) |
56
98
 
99
+ ---
57
100
 
101
+ ## Quick Start
58
102
 
59
- ## Usage
103
+ Add a container element to your HTML:
60
104
 
61
- ```js
62
- import FaceAge from 'face-age';
105
+ ```html
106
+ <div id="FaceAge-module"></div>
63
107
  ```
64
108
 
65
- To create a basic analysis with minimal configuration:
109
+ Then initialize and render:
66
110
 
67
111
  ```js
68
- const options = {
69
- elementId: 'FaceAge-module', // Required if using displayModel 'widget' or 'section'
70
- faceageId: '<Face Age Client ID>', // Your Face Age license ID
112
+ import FaceAge from 'face-age';
113
+
114
+ const faceAge = new FaceAge({
115
+ elementId: 'FaceAge-module', // your container element ID
116
+ faceageId: '<Your Client ID>', // get yours at panel.getfaceage.com
71
117
  showProducts: true,
72
118
  showRoutine: true,
73
- };
119
+ });
74
120
 
75
- const faceAge = new FaceAge(options);
76
121
  faceAge.render();
77
122
  ```
78
123
 
79
- <a href="https://panel.getfaceage.com" target="_blank" rel="noopener noreferrer">Get Face Age ID</a>
124
+ > **Get your Client ID** at [panel.getfaceage.com](https://panel.getfaceage.com) — free account required.
80
125
 
81
- For more advanced settings:
126
+ ### Full Configuration Example
82
127
 
83
128
  ```js
84
- const options = {
129
+ import FaceAge from 'face-age';
130
+
131
+ const faceAge = new FaceAge({
85
132
  elementId: 'FaceAge-module',
86
- faceageId: '<Face Age Client ID>', // Your Face Age license ID
87
- displayModel: 'section',
133
+ faceageId: '<Your Client ID>',
134
+ displayModel: 'section', // 'widget' | 'section' | 'modal'
88
135
  language: 'en',
89
136
  height: '550px',
90
137
  currency: '$',
91
- quiz: true,
92
- defaultQuiz: { email: 'hi@getfaceage.com' },
93
- showProducts: true,
94
- showRoutine: true,
95
- showAddToCart: true,
96
- problems: ['fineWrinkles', 'eyeWrinkles'],
97
- showCamera: true,
98
- showUpload: true,
99
- };
100
-
101
- const faceAge = new FaceAge(options);
102
- faceAge.render();
103
- ```
104
-
105
- ## Options
106
-
107
- You can set analysis options using `new FaceAge()`. To modify global default options, use the `options` object.
108
-
109
- ### elementId
110
-
111
- - Type: `String`
112
-
113
- Required if using the displayModel 'widget' or 'section'.
114
-
115
- ### faceageId
116
-
117
- - Type: `String`
118
-
119
- Your Face Age license ID, obtainable from the <a href="https://panel.getfaceage.com" target="_blank">panel</a> after creating an account.
120
138
 
121
- ### displayModel
122
-
123
- - Type: `String`
124
- - Default: `'section'`
125
- - Options:
126
- - `'widget'`: Only displays the analysis environment.
127
- - `'section'`: Occupies one line on the page.
128
- - `'modal'`: Shows the analysis in a full-screen modal.
129
-
130
- You can choose between different display modes.
131
-
132
- ### language
133
-
134
- - Type: `String`
135
- - Default: `'en'`
139
+ // Quiz
140
+ quiz: true,
141
+ defaultQuiz: { email: 'user@example.com' },
136
142
 
137
- Specify the desired language.
143
+ // History
144
+ history: true,
138
145
 
139
- ### width
146
+ // Products & routines
147
+ showProducts: true,
148
+ showRoutine: true,
149
+ showAddToCard: true,
150
+ showAddToCardAll: false,
151
+ routinesSupport: ['cleanser', 'serum', 'moisturizer'],
152
+ showEmptyRoutines: false,
140
153
 
141
- - Type: `Number` (optional)
154
+ // Skin problems to analyze
155
+ problems: ['fineWrinkles', 'eyeWrinkles', 'acne', 'pores'],
142
156
 
143
- Applicable when displayModel is set to `'widget'`.
157
+ // Capture
158
+ showCamera: true,
159
+ showUpload: true,
144
160
 
145
- ### height
161
+ // Legal & promotions
162
+ privacyUrl: 'https://example.com/privacy',
163
+ discount: { title: 'Use this code at checkout', code: 'FACEAGE20' },
146
164
 
147
- - Type: `Number` (optional)
165
+ // Display toggles
166
+ disableSkinHealth: false,
167
+ disableSkinAge: false,
168
+ disableImageAlert: false,
169
+ });
148
170
 
149
- Applicable when displayModel is set to `'widget'`.
171
+ faceAge.render();
172
+ ```
150
173
 
151
- ### currency
174
+ ---
152
175
 
153
- - Type: `String`
154
- - Default: `'$'`
176
+ ## Configuration Options
155
177
 
156
- Set the currency unit.
178
+ All options are passed to `new FaceAge(options)`.
157
179
 
158
- ### quiz
180
+ ### Core
159
181
 
160
- - Type: `Boolean`
161
- - Default: `true`
182
+ | Option | Type | Default | Description |
183
+ |--------|------|---------|-------------|
184
+ | `elementId` | `String` | — | **Required** for `widget` and `section` display modes. ID of the container element. |
185
+ | `faceageId` | `String` | — | **Required.** Your Face Age license ID from the [panel](https://panel.getfaceage.com). |
186
+ | `displayModel` | `String` | `'section'` | Display mode: `'widget'`, `'section'`, or `'modal'`. |
187
+ | `language` | `String` | `'en'` | UI language code. See [supported languages](#supported-languages) below. |
188
+ | `width` | `String` | `'360px'` | Width of the widget — only applies when `displayModel` is `'widget'`. |
189
+ | `height` | `String` | `'800px'` / `'580px'` | Height of the widget — defaults differ for `section` vs `widget`. |
190
+ | `currency` | `String` | `'$'` | Currency symbol shown next to product prices. |
162
191
 
163
- Toggle quiz display for users.
192
+ ### Display Modes
164
193
 
165
- ### defaultQuiz
194
+ | Mode | Behavior |
195
+ |------|----------|
196
+ | `'section'` | Renders inline, expanding to fill one content row on the page |
197
+ | `'widget'` | Renders as a fixed-size standalone panel (respects `width` and `height`) |
198
+ | `'modal'` | Opens as a full-screen overlay; no `elementId` required |
166
199
 
167
- - Type: `Object`
168
- - Example: `{ email: 'hi@getfaceage.com' }`
200
+ ### Quiz
169
201
 
170
- Prepopulate quiz fields with user information.
202
+ | Option | Type | Default | Description |
203
+ |--------|------|---------|-------------|
204
+ | `quiz` | `Boolean` | `true` | Show the pre-analysis quiz form. |
205
+ | `defaultQuiz` | `Object` | — | Pre-fill quiz fields. Example: `{ email: 'user@example.com' }`. |
171
206
 
172
- ### showProducts
207
+ ### Products & Routines
173
208
 
174
- - Type: `Boolean`
175
- - Default: `false`
209
+ | Option | Type | Default | Description |
210
+ |--------|------|---------|-------------|
211
+ | `showProducts` | `Boolean` | `false` | Show product recommendations after analysis. |
212
+ | `showRoutine` | `Boolean` | `false` | Show skincare routine groupings. |
213
+ | `showAddToCard` | `Boolean` | `true` | Show add-to-cart buttons on products. |
214
+ | `showAddToCardAll` | `Boolean` | `false` | Show a single "add all to cart" button when template supports it. |
215
+ | `routinesSupport` | `Array` | `[]` | Limit routines to specific groups, e.g. `['cleanser', 'serum', 'moisturizer']`. Empty = all groups. |
216
+ | `showEmptyRoutines` | `Boolean` | `false` | Show routine sections even when no product is matched. |
176
217
 
177
- ### showRoutine
218
+ ### Skin Analysis
178
219
 
179
- - Type: `Boolean`
180
- - Default: `false`
220
+ | Option | Type | Default | Description |
221
+ |--------|------|---------|-------------|
222
+ | `problems` | `Array` | all 13 | Skin issues to detect and display. See full list below. |
223
+ | `showCamera` | `Boolean` | `true` | Allow users to capture a photo with their camera. |
224
+ | `showUpload` | `Boolean` | `true` | Allow users to upload an image from their device. |
225
+ | `disableSkinHealth` | `Boolean` | `false` | Hide the skin health/damage summary. Alias: `disable_skin_health`. |
226
+ | `disableSkinAge` | `Boolean` | `false` | Hide the skin age result. Alias: `disable_skin_age`. |
227
+ | `disableImageAlert` | `Boolean` | `false` | Disable the image quality warning. Alias: `disable_image_alert`. |
181
228
 
182
- ### showAddToCart
229
+ **Available `problems` values:**
183
230
 
184
- - Type: `Boolean`
185
- - Default: `true`
231
+ `fineWrinkles` · `eyeWrinkles` · `deepWrinkles` · `darkCircle` · `eyeBag` · `pores` · `pigment` · `redness` · `oiliness` · `dryness` · `sagginess` · `dullness` · `acne`
186
232
 
187
- ### showCamera
233
+ ### History
188
234
 
189
- - Type: `Boolean`
190
- - Default: `true`
235
+ | Option | Type | Default | Description |
236
+ |--------|------|---------|-------------|
237
+ | `history` | `Boolean` | `false` | Enable previous-analysis history. Stored in `localStorage`/cookies by default, or inject via `faceAge.API.setHistoryData()`. |
191
238
 
192
- Allow users to capture images using the camera.
239
+ ### Promotions & Legal
193
240
 
194
- ### showUpload
241
+ | Option | Type | Default | Description |
242
+ |--------|------|---------|-------------|
243
+ | `privacyUrl` | `String` | `null` | URL to your privacy policy. Invalid URLs are silently ignored. |
244
+ | `discount` | `Object` | `null` | Show a copyable promo code. Example: `{ title: 'Code at checkout', code: 'SAVE20' }`. |
195
245
 
196
- - Type: `Boolean`
197
- - Default: `true`
246
+ ### Supported Languages
198
247
 
199
- Enable or disable image uploads.
248
+ 40 language codes are supported:
200
249
 
201
- ### problems
250
+ `ar` · `bg` · `bn` · `cs` · `da` · `de` · `el` · `en` · `es` · `et` · `fa` · `fi` · `fr` · `he` · `hi` · `hr` · `hu` · `id` · `it` · `ja` · `ko` · `lt` · `lv` · `ms` · `nl` · `no` · `pl` · `pt` · `ro` · `ru` · `sk` · `sr` · `sv` · `th` · `tl` · `tr` · `uk` · `ur` · `vi` · `zh`
202
251
 
203
- - Type: `Array`
204
- - Default: `['fineWrinkles', 'eyeWrinkles', 'deepWrinkles', 'darkCircle', 'eyeBag', 'pores', 'pigment', 'redness', 'oiliness', 'dryness', 'sagginess', 'dullness', 'acne']`
205
- - Options:
206
- - `fineWrinkles`
207
- - `eyeWrinkles`
208
- - `deepWrinkles`
209
- - `darkCircle`
210
- - `eyeBag`
211
- - `pores`
212
- - `pigment`
213
- - `redness`
214
- - `oiliness`
215
- - `dryness`
216
- - `sagginess`
217
- - `dullness`
218
- - `acne`
252
+ Arabic (`ar`), Persian (`fa`), and Urdu (`ur`) automatically switch the UI to RTL layout.
219
253
 
220
- Limit the types of skin issues displayed during analysis.
254
+ ---
221
255
 
222
256
  ## Analytics Integration
223
257
 
224
- Face Age supports integration with Google Analytics (GTM) and Facebook Pixel to track user interactions and conversions.
225
-
226
- ### Google Analytics (GTM)
258
+ Face Age fires events automatically. Connect Google Analytics or Facebook Pixel by passing your IDs as options.
227
259
 
228
- To integrate Google Analytics, add the following options:
260
+ ### Google Analytics / GTM
229
261
 
230
262
  ```js
231
- const options = {
263
+ const faceAge = new FaceAge({
232
264
  elementId: 'FaceAge-module',
233
- faceageId: '<Face Age Client ID>',
234
- gtag: 'G-XXXXXXXXXX', // Your Google Analytics Measurement ID
235
- gtagInsert: true, // Optional: Automatically inject GTM script (default: true)
236
- gtagDataLayer: window.dataLayer, // Optional: Custom dataLayer (default: window.dataLayer)
237
- };
238
-
239
- const faceAge = new FaceAge(options);
240
- faceAge.render();
265
+ faceageId: '<Your Client ID>',
266
+ gtag: 'G-XXXXXXXXXX', // G-..., GT-..., or GTM-... format
267
+ gtagInsert: true, // auto-inject GTM script (default: true)
268
+ gtagDataLayer: window.dataLayer, // optional: use a custom dataLayer
269
+ });
241
270
  ```
242
271
 
243
- #### GTM Options
244
-
245
- - **gtag** (`String`): Your Google Analytics Measurement ID (format: `G-XXXXXXXXXX`, `GT-XXXXXXXXXX`, or `GTM-XXXXXXXXXX`)
246
- - **gtagInsert** (`Boolean`, optional): Automatically inject the GTM script into the page. Default: `true`
247
- - **gtagDataLayer** (`Object`, optional): Custom dataLayer object. Default: `window.dataLayer`
248
-
249
272
  ### Facebook Pixel
250
273
 
251
- To integrate Facebook Pixel, add the following options:
252
-
253
274
  ```js
254
- const options = {
275
+ const faceAge = new FaceAge({
255
276
  elementId: 'FaceAge-module',
256
- faceageId: '<Face Age Client ID>',
257
- fbPixel: '123456789012345', // Your Facebook Pixel ID
258
- fbPixelInsert: true, // Optional: Automatically inject Facebook Pixel script (default: true)
259
- };
260
-
261
- const faceAge = new FaceAge(options);
262
- faceAge.render();
263
- ```
264
-
265
- #### Facebook Pixel Options
266
-
267
- - **fbPixel** (`String`): Your Facebook Pixel ID (numeric string)
268
- - **fbPixelInsert** (`Boolean`, optional): Automatically inject the Facebook Pixel script into the page. Default: `true`
269
-
270
- ### Using Both Analytics Services
271
-
272
- You can use both Google Analytics and Facebook Pixel simultaneously:
273
-
274
- ```js
275
- const options = {
276
- elementId: 'FaceAge-module',
277
- faceageId: '<Face Age Client ID>',
278
- gtag: 'G-XXXXXXXXXX',
279
- gtagDataLayer: window.dataLayer,
280
- fbPixel: '123456789012345',
281
- };
282
-
283
- const faceAge = new FaceAge(options);
284
- faceAge.render();
277
+ faceageId: '<Your Client ID>',
278
+ fbPixel: '123456789012345', // your numeric Pixel ID
279
+ fbPixelInsert: true, // auto-inject Pixel script (default: true)
280
+ });
285
281
  ```
286
282
 
287
283
  ### Tracked Events
288
284
 
289
- Face Age automatically tracks the following user interactions:
285
+ The following interactions are tracked automatically in both GA and Pixel:
290
286
 
291
- - Quiz start and completion
292
- - Quiz question views and choices
293
- - Skin analysis start
294
- - Photo selection and capture
295
- - Results view
296
- - Product views and interactions
297
- - Add to cart actions
298
- - Checkout button clicks
299
- - Modal open/close events
300
- - Download report actions
287
+ | Event | Description |
288
+ |-------|-------------|
289
+ | Quiz start / completion | User begins or finishes the quiz |
290
+ | Quiz question views & choices | Each question view and answer selection |
291
+ | Skin analysis start | Analysis begins |
292
+ | Photo selection / capture | Image uploaded or camera used |
293
+ | Results view | Analysis results displayed |
294
+ | Product view / interaction | Product card viewed or clicked |
295
+ | Add to cart | Add-to-cart button clicked |
296
+ | Checkout | Checkout button clicked |
297
+ | Modal open / close | Modal opened or dismissed |
298
+ | Download report | PDF report download initiated |
301
299
 
302
- ## API
300
+ ---
303
301
 
304
- Once the image is analyzed, you can retrieve the results using the following commands:
302
+ ## API Reference
305
303
 
306
- ### Get Advisor Data
304
+ After calling `faceAge.render()`, use `faceAge.API` to read results and interact with the SDK programmatically.
307
305
 
308
- Retrieve advisor data after the analysis:
306
+ ### Read Analysis Results
309
307
 
310
308
  ```js
311
309
  faceAge.API.getAdvisorData((data) => {
312
- console.log('Advisor data analysis:', data);
310
+ console.log(data.analysis); // skin age, damage %, detected problems
311
+ console.log(data.activeSelections); // quiz answers
313
312
  });
314
313
  ```
315
314
 
316
- ### Get Active Selections
317
-
318
- Retrieve active selections after completing the form:
315
+ ### Read Quiz Answers
319
316
 
320
317
  ```js
321
318
  faceAge.API.getActiveSelections((data) => {
322
- console.log('Quiz active selection data:', data);
319
+ console.log(data); // { email, skinType, ... }
323
320
  });
324
321
  ```
325
322
 
326
- ### Get Routine Groups
323
+ ### Read the Submitted Image
327
324
 
328
- Retrieve routine groups that the software supports:
325
+ ```js
326
+ const image = faceAge.API.getImage();
327
+ ```
328
+
329
+ ### Read Available Routine Groups
329
330
 
330
331
  ```js
331
- console.log('Routine Groups:', faceAge.API.getRoutineGroup());
332
+ const groups = faceAge.API.getRoutineGroup();
332
333
  ```
333
334
 
334
- ### Add Custom Products
335
+ ### Set Custom Products
335
336
 
336
- Manually add and display custom products:
337
+ Push your own product catalog into the SDK — it will match products to detected skin problems automatically.
337
338
 
338
339
  ```js
339
340
  faceAge.API.setCustomProducts([
340
341
  {
341
342
  id: 1,
342
- url: 'https://getfaceage.com',
343
- image: 'https://demo.getfaceage.com/static/products/pr5.png',
344
- title: 'Skin moisturizers',
345
- description: 'Vitamin C. Rooster 30ml', //optional
346
- routineGroups: {'morning': ['cleanser', 'serum']}, //optional
347
- problems: ['acne', 'wrinkles'], //optional
343
+ url: 'https://yourstore.com/product',
344
+ image: 'https://yourstore.com/product.png',
345
+ title: 'Skin Moisturizer',
346
+ description: 'Vitamin C · 30ml', // optional
348
347
  price: 40,
349
- offerPrice: 18.99, //optional
350
- variables: { //optional
351
- 'size': {
348
+ offerPrice: 18.99, // optional sale price
349
+ problems: ['acne', 'wrinkles'], // optional: target problems
350
+ routineGroups: { morning: ['cleanser', 'serum'] }, // optional
351
+ variables: { // optional: size/variant picker
352
+ size: {
352
353
  title: 'Size',
353
354
  option: [
354
- {label: '10 cc', value: '10', price: 40 /*optional*/, offerPrice: 18.99 /*optional*/},
355
- {label: '25 cc', value: '25', price: 52 /*optional*/, offerPrice: 19.99 /*optional*/},
356
- {label: '35 cc', value: '35'}
357
- ]
358
- }
355
+ { label: '10 cc', value: '10', price: 40, offerPrice: 18.99 },
356
+ { label: '25 cc', value: '25', price: 52 },
357
+ { label: '35 cc', value: '35' },
358
+ ],
359
+ },
359
360
  },
360
- }
361
+ },
361
362
  ]);
362
363
  ```
363
364
 
364
- ## Complete Example of API Usage
365
+ ### History Management
365
366
 
366
- ```js
367
- faceAge.API.getAdvisorData((data) => {
368
- // Use the data from the analysis
369
- console.log('Advisor data analysis:', data);
370
-
371
- console.log('User Image:', faceAge.API.getImage());
372
-
373
- faceAge.API.getActiveSelections((data) => {
374
- console.log('Quiz active selection data:', data);
375
- });
376
-
377
- faceAge.API.setCustomProducts([
378
- {
379
- id: 1,
380
- url: 'https://getfaceage.com',
381
- image: 'https://demo.getfaceage.com/static/products/pr5.png',
382
- title: 'Skin moisturizers',
383
- description: 'Vitamin C. Rooster 30ml', //optional
384
- routineGroups: {'morning': ['cleanser', 'serum']}, //optional
385
- problems: ['acne', 'wrinkles'], //optional
386
- price: 40,
387
- offerPrice: 18.99, //optional
388
- }
389
- ]);
367
+ **Restore history from your backend** (requires `history: true`):
390
368
 
369
+ ```js
370
+ faceAge.API.setHistoryData({
371
+ analysis: {
372
+ analyze_ref_token: 'analyze_ref_abc123',
373
+ skinAge: 28,
374
+ damagePercentage: 12.4,
375
+ problems: [],
376
+ },
377
+ activeSelections: {
378
+ email: 'user@example.com',
379
+ skinType: 'combination',
380
+ },
381
+ meta: {
382
+ ts: Date.now(),
383
+ image: 'https://example.com/scan.jpg',
384
+ },
391
385
  });
392
386
  ```
393
387
 
394
- ## Events
395
-
396
- Add custom event listeners for different interactions:
397
-
398
- ### onClickProblem
388
+ **Remove a history entry** by reference token. Pass `null` to clear all local history:
399
389
 
400
390
  ```js
401
- faceAge.onClickProblem((key) => {
402
- // Get user status and information when they click on a problem
403
- console.log('User clicked on problem:', key);
391
+ faceAge.API.removeHistoryItem('analyze_ref_abc123').then((removed) => {
392
+ console.log('Removed:', removed);
404
393
  });
405
394
  ```
406
395
 
407
- ### onDisplayProducts
396
+ ### Generate PDF Report
397
+
398
+ Requires PDF access on your Face Age plan.
408
399
 
409
400
  ```js
410
- faceAge.onDisplayProducts((data) => {
411
- // Display product information when the product list is shown
412
- console.log('Display Products:', data);
413
- });
401
+ faceAge.API.getReportPdf()
402
+ .then((report) => console.log('Report:', report))
403
+ .catch((err) => console.error('Failed:', err));
414
404
  ```
415
405
 
416
- ### onDisplayRoutines
406
+ ### Submit SDK Integration
407
+
408
+ Send the full analysis payload (skin results, products, quiz data, brand metadata) to the SDK-call integration endpoint. If no email is provided, Face Age falls back to `email` or `clientEmail` from quiz answers.
417
409
 
418
410
  ```js
419
- faceAge.onDisplayRoutines((data) => {
420
- // Display routine information when the routine list is shown
421
- console.log('Display Routines:', data);
411
+ // Basic
412
+ faceAge.API.submitSdkIntegration('user@example.com').then((res) => {
413
+ console.log('Submitted:', res);
422
414
  });
423
- ```
424
415
 
425
- ### onAddToCart
426
-
427
- ```js
428
- faceAge.onAddToCart((data) => {
429
- // Retrieve product information when a user clicks add to cart
430
- console.log('User clicked add to cart:', data);
416
+ // With extra metadata
417
+ faceAge.API.submitSdkIntegration('user@example.com', {
418
+ name: 'Jane Doe',
419
+ skinType: 'dry',
420
+ skinConcern: ['fineWrinkles', 'dryness'],
431
421
  });
432
422
  ```
433
423
 
434
- ### onClickProduct
424
+ Quiz data is automatically normalized to `[{ question, answer }]` before submission.
435
425
 
436
- ```js
437
- faceAge.onClickProduct((product) => {
438
- // Retrieve product details when a user clicks on a product
439
- console.log('User clicked on product info:', product);
440
- });
441
- ```
426
+ ---
442
427
 
443
- ### onResetData
428
+ ## Events
444
429
 
445
- ```js
446
- faceAge.onResetData(() => {
447
- // Trigger when the user refreshes the information
448
- console.log('User clicked reset data');
449
- });
450
- ```
430
+ Register callbacks to react to user interactions in real time.
431
+
432
+ | Event | Callback signature | Fires when |
433
+ |-------|--------------------|------------|
434
+ | `onClickProblem` | `(key: string)` | User taps a skin problem in the results |
435
+ | `onDisplayProducts` | `(data)` | Product list becomes visible |
436
+ | `onDisplayRoutines` | `(data)` | Routine list becomes visible |
437
+ | `onAddToCart` | `(data)` | User clicks add to cart |
438
+ | `onClickProduct` | `(product)` | User clicks a product card |
439
+ | `onResetData` | `()` | User clicks reset / start over |
440
+ | `onCloseModal` | `()` | User closes the modal |
441
+ | `onCheckout` | `(data)` | User clicks the checkout button |
451
442
 
452
- ### onCloseModal
443
+ **Example:**
453
444
 
454
445
  ```js
455
- faceAge.onCloseModal(() => {
456
- // Trigger when the user closes the modal. You could forward them to checkout if products were added to cart.
457
- console.log('User clicked close');
446
+ faceAge.onAddToCart((data) => {
447
+ // data contains product details
448
+ myCart.add(data);
458
449
  });
459
- ```
460
450
 
461
- ### onCheckout
451
+ faceAge.onCloseModal(() => {
452
+ // redirect to cart if items were added
453
+ if (myCart.hasItems()) window.location.href = '/cart';
454
+ });
462
455
 
463
- ```js
464
- faceAge.onCheckout((data) => {
465
- // Trigger when the user clicks the checkout button
466
- console.log('User clicked checkout');
456
+ faceAge.onClickProblem((key) => {
457
+ console.log('Problem selected:', key); // e.g. 'acne'
467
458
  });
468
459
  ```
469
460
 
470
- ## New Features
471
-
472
- - **Face Mask & Skin Routine:** Display skin routine products and allow users to manage their routines.
473
- - **Summary of Skin Information:** Provide users with a summary of their skin analysis.
474
- - **Multiple Languages:** Support for multiple languages and custom labels.
475
- - **Customizable Themes:** Customizable themes and layouts to match user preferences.
461
+ ---
476
462
 
477
463
  ## Contact
478
464
 
479
- - Website: [getfaceage.com](https://getfaceage.com/)
480
- - Panel: [panel.getfaceage.com](https://panel.getfaceage.com/)
481
- - Email: [dev@getfaceage.com](mailto:dev@getfaceage.com)
482
-
465
+ | | |
466
+ |--|--|
467
+ | Website | [getfaceage.com](https://getfaceage.com/) |
468
+ | Dashboard | [panel.getfaceage.com](https://panel.getfaceage.com/) |
469
+ | Email | [dev@getfaceage.com](mailto:dev@getfaceage.com) |