@clianta/sdk 1.5.0 → 1.5.1

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,22 @@ All notable changes to the Clianta SDK will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.5.1] - 2026-02-28
9
+
10
+ ### Added
11
+ - **Public CRM API** — Frontend-safe CRM methods that don't require an API key (secured by domain whitelist):
12
+ - `createContact()` — Create or upsert a contact by email
13
+ - `updateContact()` — Update an existing contact by ID
14
+ - `submitForm()` — Submit a form and auto-create/update contact
15
+ - `logActivity()` — Append an activity to a contact
16
+ - `createOpportunity()` — Create an opportunity (e.g., from "Request Demo" forms)
17
+ - **Public CRM types** — `PublicContactData`, `PublicContactUpdate`, `PublicFormSubmission`, `PublicActivityData`, `PublicOpportunityData`, `PublicCrmResult`
18
+ - **Updated docs** — API Reference and Getting Started guides updated with public CRM usage
19
+
20
+ ### Changed
21
+ - Config: improved `getDefaultApiEndpoint()` with env variable support
22
+ - Framework integrations: minor fixes for Angular, Svelte, Vue, React
23
+
8
24
  ## [1.5.0] - 2026-02-28
9
25
 
10
26
  ### Security
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * Clianta SDK v1.5.0
2
+ * Clianta SDK v1.5.1
3
3
  * (c) 2026 Clianta
4
4
  * Released under the MIT License.
5
5
  */
@@ -11,15 +11,22 @@
11
11
  */
12
12
  /** SDK Version */
13
13
  const SDK_VERSION = '1.4.0';
14
- /** Default API endpoint based on environment */
14
+ /** Default API endpoint reads from env or falls back to localhost */
15
15
  const getDefaultApiEndpoint = () => {
16
- if (typeof window === 'undefined')
17
- return 'https://api.clianta.online';
18
- const hostname = window.location.hostname;
19
- if (hostname.includes('localhost') || hostname.includes('127.0.0.1')) {
20
- return 'http://localhost:5000';
16
+ // Build-time env var (works with Next.js, Vite, CRA, etc.)
17
+ if (typeof process !== 'undefined' && process.env?.NEXT_PUBLIC_CLIANTA_API_ENDPOINT) {
18
+ return process.env.NEXT_PUBLIC_CLIANTA_API_ENDPOINT;
19
+ }
20
+ if (typeof process !== 'undefined' && process.env?.VITE_CLIANTA_API_ENDPOINT) {
21
+ return process.env.VITE_CLIANTA_API_ENDPOINT;
22
+ }
23
+ if (typeof process !== 'undefined' && process.env?.REACT_APP_CLIANTA_API_ENDPOINT) {
24
+ return process.env.REACT_APP_CLIANTA_API_ENDPOINT;
21
25
  }
22
- return 'https://api.clianta.online';
26
+ if (typeof process !== 'undefined' && process.env?.CLIANTA_API_ENDPOINT) {
27
+ return process.env.CLIANTA_API_ENDPOINT;
28
+ }
29
+ return 'http://localhost:5000';
23
30
  };
24
31
  /** Core plugins enabled by default */
25
32
  const DEFAULT_PLUGINS = [
@@ -1781,7 +1788,7 @@ class PopupFormsPlugin extends BasePlugin {
1781
1788
  return;
1782
1789
  const config = this.tracker.getConfig();
1783
1790
  const workspaceId = this.tracker.getWorkspaceId();
1784
- const apiEndpoint = config.apiEndpoint || 'https://api.clianta.online';
1791
+ const apiEndpoint = config.apiEndpoint || 'http://localhost:5000';
1785
1792
  try {
1786
1793
  const url = encodeURIComponent(window.location.href);
1787
1794
  const response = await fetch(`${apiEndpoint}/api/public/lead-forms/${workspaceId}?url=${url}`);
@@ -1886,7 +1893,7 @@ class PopupFormsPlugin extends BasePlugin {
1886
1893
  if (!this.tracker)
1887
1894
  return;
1888
1895
  const config = this.tracker.getConfig();
1889
- const apiEndpoint = config.apiEndpoint || 'https://api.clianta.online';
1896
+ const apiEndpoint = config.apiEndpoint || 'http://localhost:5000';
1890
1897
  try {
1891
1898
  await fetch(`${apiEndpoint}/api/public/lead-forms/${formId}/view`, {
1892
1899
  method: 'POST',
@@ -2133,7 +2140,7 @@ class PopupFormsPlugin extends BasePlugin {
2133
2140
  if (!this.tracker)
2134
2141
  return;
2135
2142
  const config = this.tracker.getConfig();
2136
- const apiEndpoint = config.apiEndpoint || 'https://api.clianta.online';
2143
+ const apiEndpoint = config.apiEndpoint || 'http://localhost:5000';
2137
2144
  const visitorId = this.tracker.getVisitorId();
2138
2145
  // Collect form data
2139
2146
  const formData = new FormData(formElement);
@@ -3028,7 +3035,7 @@ class CRMClient {
3028
3035
  * The contact is upserted in the CRM and matching workflow automations fire automatically.
3029
3036
  *
3030
3037
  * @example
3031
- * const crm = new CRMClient('https://api.clianta.online', 'WORKSPACE_ID');
3038
+ * const crm = new CRMClient('http://localhost:5000', 'WORKSPACE_ID');
3032
3039
  * crm.setApiKey('mm_live_...');
3033
3040
  *
3034
3041
  * await crm.sendEvent({
@@ -4168,6 +4175,86 @@ class Tracker {
4168
4175
  this.sessionId = this.createSessionId();
4169
4176
  logger.info('All user data deleted');
4170
4177
  }
4178
+ // ============================================
4179
+ // PUBLIC CRM METHODS (no API key required)
4180
+ // ============================================
4181
+ /**
4182
+ * Create or update a contact by email (upsert).
4183
+ * Secured by domain whitelist — no API key needed.
4184
+ */
4185
+ async createContact(data) {
4186
+ return this.publicCrmRequest('/api/public/crm/contacts', 'POST', {
4187
+ workspaceId: this.workspaceId,
4188
+ ...data,
4189
+ });
4190
+ }
4191
+ /**
4192
+ * Update an existing contact by ID (limited fields only).
4193
+ */
4194
+ async updateContact(contactId, data) {
4195
+ return this.publicCrmRequest(`/api/public/crm/contacts/${contactId}`, 'PUT', {
4196
+ workspaceId: this.workspaceId,
4197
+ ...data,
4198
+ });
4199
+ }
4200
+ /**
4201
+ * Submit a form — creates/updates contact from form data.
4202
+ */
4203
+ async submitForm(formId, data) {
4204
+ const payload = {
4205
+ ...data,
4206
+ metadata: {
4207
+ ...data.metadata,
4208
+ visitorId: this.visitorId,
4209
+ sessionId: this.sessionId,
4210
+ pageUrl: typeof window !== 'undefined' ? window.location.href : undefined,
4211
+ referrer: typeof document !== 'undefined' ? document.referrer || undefined : undefined,
4212
+ },
4213
+ };
4214
+ return this.publicCrmRequest(`/api/public/crm/forms/${formId}/submit`, 'POST', payload);
4215
+ }
4216
+ /**
4217
+ * Log an activity linked to a contact (append-only).
4218
+ */
4219
+ async logActivity(data) {
4220
+ return this.publicCrmRequest('/api/public/crm/activities', 'POST', {
4221
+ workspaceId: this.workspaceId,
4222
+ ...data,
4223
+ });
4224
+ }
4225
+ /**
4226
+ * Create an opportunity (e.g., from "Request Demo" forms).
4227
+ */
4228
+ async createOpportunity(data) {
4229
+ return this.publicCrmRequest('/api/public/crm/opportunities', 'POST', {
4230
+ workspaceId: this.workspaceId,
4231
+ ...data,
4232
+ });
4233
+ }
4234
+ /**
4235
+ * Internal helper for public CRM API calls.
4236
+ */
4237
+ async publicCrmRequest(path, method, body) {
4238
+ const url = `${this.config.apiEndpoint}${path}`;
4239
+ try {
4240
+ const response = await fetch(url, {
4241
+ method,
4242
+ headers: { 'Content-Type': 'application/json' },
4243
+ body: JSON.stringify(body),
4244
+ });
4245
+ const data = await response.json().catch(() => ({}));
4246
+ if (response.ok) {
4247
+ logger.debug(`Public CRM ${method} ${path} succeeded`);
4248
+ return { success: true, data: data.data ?? data, status: response.status };
4249
+ }
4250
+ logger.error(`Public CRM ${method} ${path} failed (${response.status}):`, data.message);
4251
+ return { success: false, error: data.message, status: response.status };
4252
+ }
4253
+ catch (error) {
4254
+ logger.error(`Public CRM ${method} ${path} error:`, error);
4255
+ return { success: false, error: error.message };
4256
+ }
4257
+ }
4171
4258
  /**
4172
4259
  * Destroy tracker and cleanup
4173
4260
  */
@@ -4292,7 +4379,7 @@ if (typeof window !== 'undefined') {
4292
4379
  * @example
4293
4380
  * const instance = createCliantaTracker({
4294
4381
  * projectId: 'your-project-id',
4295
- * apiEndpoint: 'https://api.clianta.online',
4382
+ * apiEndpoint: environment.cliantaApiEndpoint || 'http://localhost:5000',
4296
4383
  * });
4297
4384
  *
4298
4385
  * instance.tracker?.track('page_view', 'Home Page');