n8n-nodes-chatads 0.1.3 → 0.1.5

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
@@ -44,9 +44,9 @@ The node accepts the following fields (via parameters or `Extra Fields (JSON)`):
44
44
  | Field | Type | Description |
45
45
  |-------|------|-------------|
46
46
  | `message` | string (required) | Message to analyze (1-5000 chars) |
47
- | `ip` | string | Client IP address for geo-detection |
48
- | `country` | string | ISO 3166-1 alpha-2 country code for geo-targeting |
49
- | `message_analysis` | string | Extraction method: `"fast"`, `"balanced"` (default), `"thorough"` |
50
- | `fill_priority` | string | URL resolution: `"speed"` or `"coverage"` (default) |
51
- | `min_intent` | string | Intent filter: `"any"`, `"low"` (default), `"medium"`, `"high"` |
52
- | `skip_message_analysis` | boolean | Skip NLP/LLM and use message directly as search query |
47
+ | `ip` | string | IPv4 address for country detection (max 64 characters) |
48
+ | `country` | string | Country code (e.g., 'US'). If provided, skips IP-based country detection |
49
+ | `message_analysis` | string | Controls keyword extraction method. Use 'fast' to optimize for speed, 'thorough' (default) to optimize for best keyword selection |
50
+ | `fill_priority` | string | Controls affiliate link discovery. Use 'speed' to optimize for speed, 'coverage' (default) to ping multiple sources for the right affiliate link |
51
+ | `min_intent` | string | Minimum purchase intent level required for affiliate resolution. 'any' = no filtering, 'low' (default) = filter garbage, 'medium' = balanced quality/fill, 'high' = high-intent keywords only |
52
+ | `skip_message_analysis` | boolean | Treat exact message as product keyword. When true, goes straight to affiliate link discovery without keyword extraction |
@@ -10,8 +10,8 @@ class ChatAdsApi {
10
10
  displayName: 'Base URL',
11
11
  name: 'baseUrl',
12
12
  type: 'string',
13
- default: 'https://app.getchatads.com',
14
- description: 'Root domain where the ChatAds FastAPI service (affiliate/chatads_backend.py) is deployed',
13
+ default: 'https://api.getchatads.com',
14
+ description: 'ChatAds API endpoint URL',
15
15
  },
16
16
  {
17
17
  displayName: 'API Key',
@@ -36,7 +36,7 @@ class ChatAdsApi {
36
36
  this.test = {
37
37
  request: {
38
38
  method: 'GET',
39
- url: '={{($credentials.baseUrl || "").replace(/\/+$/, "") || "https://app.getchatads.com"}}',
39
+ url: '={{($credentials.baseUrl || "").replace(/\/+$/, "") || "https://api.getchatads.com"}}',
40
40
  qs: {
41
41
  source: 'n8n-credential-test',
42
42
  },
@@ -10,6 +10,8 @@ const OPTIONAL_FIELDS = new Set([
10
10
  'fill_priority',
11
11
  'min_intent',
12
12
  'skip_message_analysis',
13
+ 'demo',
14
+ 'max_offers',
13
15
  ]);
14
16
  const FIELD_ALIASES = {
15
17
  messageanalysis: 'message_analysis',
@@ -20,6 +22,8 @@ const FIELD_ALIASES = {
20
22
  min_intent: 'min_intent',
21
23
  skipmessageanalysis: 'skip_message_analysis',
22
24
  skip_message_analysis: 'skip_message_analysis',
25
+ maxoffers: 'max_offers',
26
+ max_offers: 'max_offers',
23
27
  };
24
28
  const RESERVED_PAYLOAD_KEYS = new Set(['message', ...OPTIONAL_FIELDS]);
25
29
  const isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
@@ -90,13 +94,20 @@ const buildPayloadFromObject = (context, input, source, itemIndex) => {
90
94
  }
91
95
  const optionalKey = normalizeOptionalField(rawKey);
92
96
  if (optionalKey) {
93
- if (optionalKey === 'skip_message_analysis') {
97
+ if (optionalKey === 'skip_message_analysis' || optionalKey === 'demo') {
94
98
  if (typeof rawValue !== 'boolean') {
95
99
  throw new n8n_workflow_1.NodeOperationError(context.getNode(), `${source} field "${rawKey}" must be a boolean`, { itemIndex });
96
100
  }
97
101
  payload[optionalKey] = rawValue;
98
102
  continue;
99
103
  }
104
+ if (optionalKey === 'max_offers') {
105
+ if (typeof rawValue !== 'number') {
106
+ throw new n8n_workflow_1.NodeOperationError(context.getNode(), `${source} field "${rawKey}" must be a number`, { itemIndex });
107
+ }
108
+ payload[optionalKey] = rawValue;
109
+ continue;
110
+ }
100
111
  payload[optionalKey] = coerceToString(context, source, rawKey, rawValue, itemIndex);
101
112
  continue;
102
113
  }
@@ -220,14 +231,14 @@ class ChatAds {
220
231
  name: 'ip',
221
232
  type: 'string',
222
233
  default: '',
223
- description: 'Client IP address for geo-detection',
234
+ description: 'IPv4/IPv6 address for country detection (max 45 characters)',
224
235
  },
225
236
  {
226
237
  displayName: 'Country',
227
238
  name: 'country',
228
239
  type: 'string',
229
240
  default: '',
230
- description: 'ISO 3166-1 alpha-2 country code for geo-targeting',
241
+ description: "Country code (e.g., 'US'). If provided, skips IP-based country detection",
231
242
  },
232
243
  {
233
244
  displayName: 'Message Analysis',
@@ -235,11 +246,10 @@ class ChatAds {
235
246
  type: 'options',
236
247
  options: [
237
248
  { name: 'Fast', value: 'fast' },
238
- { name: 'Balanced', value: 'balanced' },
239
249
  { name: 'Thorough', value: 'thorough' },
240
250
  ],
241
- default: 'balanced',
242
- description: 'Keyword extraction method. Fast uses NLP only (~50ms), others use LLM.',
251
+ default: 'thorough',
252
+ description: 'Controls keyword extraction method. Use fast to optimize for speed, thorough to optimize for best keyword selection.',
243
253
  },
244
254
  {
245
255
  displayName: 'Fill Priority',
@@ -250,7 +260,7 @@ class ChatAds {
250
260
  { name: 'Coverage', value: 'coverage' },
251
261
  ],
252
262
  default: 'coverage',
253
- description: 'URL resolution fallback strategy',
263
+ description: 'Controls affiliate link discovery. Use speed to optimize for speed, coverage to ping multiple sources for the right affiliate link',
254
264
  },
255
265
  {
256
266
  displayName: 'Min Intent',
@@ -263,14 +273,32 @@ class ChatAds {
263
273
  { name: 'High', value: 'high' },
264
274
  ],
265
275
  default: 'low',
266
- description: 'Minimum purchase intent level for affiliate resolution',
276
+ description: "Minimum purchase intent level required for affiliate resolution. 'any' = no filtering, 'low' = filter garbage, 'medium' = balanced quality/fill, 'high' = high-intent keywords only",
267
277
  },
268
278
  {
269
279
  displayName: 'Skip Message Analysis',
270
280
  name: 'skip_message_analysis',
271
281
  type: 'boolean',
272
282
  default: false,
273
- description: 'Skip NLP/LLM extraction and use message directly as search query. Overrides message_analysis, min_intent, and fill_priority.',
283
+ description: 'Treat exact message as product keyword. When true, goes straight to affiliate link discovery without keyword extraction',
284
+ },
285
+ {
286
+ displayName: 'Demo Mode',
287
+ name: 'demo',
288
+ type: 'boolean',
289
+ default: false,
290
+ description: 'Enable demo mode',
291
+ },
292
+ {
293
+ displayName: 'Max Offers',
294
+ name: 'max_offers',
295
+ type: 'number',
296
+ typeOptions: {
297
+ minValue: 1,
298
+ maxValue: 2,
299
+ },
300
+ default: 1,
301
+ description: 'Maximum number of affiliate offers to return (1-2)',
274
302
  },
275
303
  {
276
304
  displayName: 'Extra Fields (JSON)',
@@ -376,13 +404,20 @@ class ChatAds {
376
404
  if (!normalizedKey) {
377
405
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Field "${field}" is not supported`, { itemIndex });
378
406
  }
379
- if (normalizedKey === 'skip_message_analysis') {
407
+ if (normalizedKey === 'skip_message_analysis' || normalizedKey === 'demo') {
380
408
  if (typeof value !== 'boolean') {
381
409
  throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Field "${field}" must be provided as a boolean`, { itemIndex });
382
410
  }
383
411
  constructed[normalizedKey] = value;
384
412
  continue;
385
413
  }
414
+ if (normalizedKey === 'max_offers') {
415
+ if (typeof value !== 'number') {
416
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Field "${field}" must be provided as a number`, { itemIndex });
417
+ }
418
+ constructed[normalizedKey] = value;
419
+ continue;
420
+ }
386
421
  constructed[normalizedKey] = coerceToString(this, 'Additional fields', field, value, itemIndex);
387
422
  }
388
423
  body = buildPayloadFromObject(this, constructed, 'Additional fields', itemIndex);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-chatads",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "n8n wrapper around the ChatAds FastAPI backend (affiliate/chatads_backend.py)",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",