@caruuto/caruuto-js 0.6.0 → 0.8.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
6
  and this project adheres to [Semantic Versioning](http://semver.org/).
7
7
 
8
+ ## 0.7.0 - 2026-06-08
9
+
10
+ ### Added
11
+
12
+ - `ai.query()`, `ai.stream()`, and `ai.context()` now accept `utmSource`,
13
+ `utmMedium`, `utmCampaign`, `utmTerm`, and `utmContent` options, sent through
14
+ as `utm_source` / `utm_medium` / `utm_campaign` / `utm_term` / `utm_content`
15
+ alongside the existing `referrerUrl`. Lets callers forward acquisition data
16
+ from the page URL so Caruuto can attribute AI sessions to a referral channel.
17
+
8
18
  ## 0.3.6 - 2024-09-06
9
19
 
10
20
  ### Added
@@ -13,6 +13,11 @@ module.exports = function (CaruutoClient, clientInstance) {
13
13
  * @param {string} [opts.clientSessionId] - Client's anonymous user token
14
14
  * @param {string} [opts.source] - 'widget' | 'api' | 'embed'
15
15
  * @param {string} [opts.referrerUrl] - URL where the chat is embedded
16
+ * @param {string} [opts.utmSource] - UTM source param from the page URL
17
+ * @param {string} [opts.utmMedium] - UTM medium param from the page URL
18
+ * @param {string} [opts.utmCampaign] - UTM campaign param from the page URL
19
+ * @param {string} [opts.utmTerm] - UTM term param from the page URL
20
+ * @param {string} [opts.utmContent] - UTM content param from the page URL
16
21
  * @param {string} [opts.leadEmail] - Capture a lead email on this turn
17
22
  * @param {string} [opts.leadName] - Lead name (paired with leadEmail)
18
23
  * @param {string} [opts.type] - Restrict retrieval to a single knowledge type
@@ -137,6 +142,11 @@ module.exports = function (CaruutoClient, clientInstance) {
137
142
  clientSessionId,
138
143
  source,
139
144
  referrerUrl,
145
+ utmSource,
146
+ utmMedium,
147
+ utmCampaign,
148
+ utmTerm,
149
+ utmContent,
140
150
  type,
141
151
  maxItems
142
152
  } = opts
@@ -147,6 +157,11 @@ module.exports = function (CaruutoClient, clientInstance) {
147
157
  if (clientSessionId) body.client_session_id = clientSessionId
148
158
  if (source) body.source = source
149
159
  if (referrerUrl) body.referrer_url = referrerUrl
160
+ if (utmSource) body.utm_source = utmSource
161
+ if (utmMedium) body.utm_medium = utmMedium
162
+ if (utmCampaign) body.utm_campaign = utmCampaign
163
+ if (utmTerm) body.utm_term = utmTerm
164
+ if (utmContent) body.utm_content = utmContent
150
165
  if (type) body.type = type
151
166
  if (maxItems !== undefined) body.max_items = maxItems
152
167
 
@@ -304,6 +319,49 @@ module.exports = function (CaruutoClient, clientInstance) {
304
319
  const url = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}/turn`
305
320
  const response = await doFetch(this, url, body)
306
321
  return response.json()
322
+ }.bind(clientInstance),
323
+
324
+ /**
325
+ * Record a click on a link surfaced in an assistant response — powers the
326
+ * CTA-click and conversion panels on the analytics dashboard. Caruuto
327
+ * classifies the link as 'internal' or 'external' relative to the
328
+ * project's site_domain and persists it to ai_link_click_events.
329
+ *
330
+ * @param {Object} opts
331
+ * @param {string} opts.conversationId - The conversation the link appeared in
332
+ * @param {string} opts.projectId
333
+ * @param {string} opts.url - The full clicked URL, exactly as rendered
334
+ * @param {string} [opts.linkLabel] - The link's visible text
335
+ * @param {number} [opts.messageIndex] - Position of the assistant message clicked from
336
+ * @returns {Promise<{ ok: boolean }>}
337
+ */
338
+ trackLinkClick: async function ({
339
+ conversationId,
340
+ projectId,
341
+ url,
342
+ linkLabel,
343
+ messageIndex
344
+ } = {}) {
345
+ if (!conversationId) {
346
+ throw new Error('conversationId is required')
347
+ }
348
+
349
+ if (!projectId) {
350
+ throw new Error('projectId is required')
351
+ }
352
+
353
+ if (!url) {
354
+ throw new Error('url is required')
355
+ }
356
+
357
+ const body = { project_id: projectId, url }
358
+
359
+ if (linkLabel) body.link_label = linkLabel
360
+ if (messageIndex !== undefined) body.message_index = messageIndex
361
+
362
+ const trackUrl = `${this.options.caruutoUrl}/api/ai/conversations/${conversationId}/link-click`
363
+ const response = await doFetch(this, trackUrl, body)
364
+ return response.json()
307
365
  }.bind(clientInstance)
308
366
  }
309
367
  }
@@ -320,6 +378,11 @@ function buildRequestBody(opts, stream) {
320
378
  clientSessionId,
321
379
  source,
322
380
  referrerUrl,
381
+ utmSource,
382
+ utmMedium,
383
+ utmCampaign,
384
+ utmTerm,
385
+ utmContent,
323
386
  leadEmail,
324
387
  leadName,
325
388
  type,
@@ -332,6 +395,11 @@ function buildRequestBody(opts, stream) {
332
395
  if (clientSessionId) body.client_session_id = clientSessionId
333
396
  if (source) body.source = source
334
397
  if (referrerUrl) body.referrer_url = referrerUrl
398
+ if (utmSource) body.utm_source = utmSource
399
+ if (utmMedium) body.utm_medium = utmMedium
400
+ if (utmCampaign) body.utm_campaign = utmCampaign
401
+ if (utmTerm) body.utm_term = utmTerm
402
+ if (utmContent) body.utm_content = utmContent
335
403
  if (leadEmail) body.lead_email = leadEmail
336
404
  if (leadName) body.lead_name = leadName
337
405
  if (type) body.type = type
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caruuto/caruuto-js",
3
- "version": "0.6.0",
3
+ "version": "0.8.0",
4
4
  "description": "A high-level library for interacting with Caruuto",
5
5
  "exports": "./index.js",
6
6
  "scripts": {