@seranking/n8n-nodes-seranking 1.5.12 → 2.0.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.
Files changed (29) hide show
  1. package/README.md +17 -10
  2. package/dist/credentials/SeRankingApi.credentials.js +2 -2
  3. package/dist/nodes/SeRanking/SeRanking.node.d.ts +6 -1
  4. package/dist/nodes/SeRanking/SeRanking.node.js +41 -36
  5. package/dist/nodes/SeRanking/projectApi/descriptions/AiResultTrackerDescription.js +11 -0
  6. package/dist/nodes/SeRanking/projectApi/descriptions/AirtGroupsDescription.d.ts +3 -0
  7. package/dist/nodes/SeRanking/projectApi/descriptions/AirtGroupsDescription.js +231 -0
  8. package/dist/nodes/SeRanking/projectApi/descriptions/ProjectManagementDescription.js +127 -0
  9. package/dist/nodes/SeRanking/projectApi/descriptions/WebsiteAuditDescription.js +114 -5
  10. package/dist/nodes/SeRanking/projectApi/operations/AccountSystemOperations.js +2 -2
  11. package/dist/nodes/SeRanking/projectApi/operations/AiResultTrackerOperations.js +20 -18
  12. package/dist/nodes/SeRanking/projectApi/operations/AirtGroupsOperations.d.ts +2 -0
  13. package/dist/nodes/SeRanking/projectApi/operations/AirtGroupsOperations.js +93 -0
  14. package/dist/nodes/SeRanking/projectApi/operations/AnalyticsTrafficOperations.js +3 -3
  15. package/dist/nodes/SeRanking/projectApi/operations/BacklinkCheckerOperations.js +19 -20
  16. package/dist/nodes/SeRanking/projectApi/operations/CompetitorsOperations.js +11 -8
  17. package/dist/nodes/SeRanking/projectApi/operations/GeneralDataOperations.js +7 -8
  18. package/dist/nodes/SeRanking/projectApi/operations/KeywordGroupsOperations.js +6 -6
  19. package/dist/nodes/SeRanking/projectApi/operations/MarketingPlanOperations.js +5 -5
  20. package/dist/nodes/SeRanking/projectApi/operations/ProjectGroupsOperations.js +6 -6
  21. package/dist/nodes/SeRanking/projectApi/operations/ProjectManagementOperations.js +70 -32
  22. package/dist/nodes/SeRanking/projectApi/operations/SearchVolumeOperations.js +5 -22
  23. package/dist/nodes/SeRanking/projectApi/operations/SubAccountOperations.js +8 -8
  24. package/dist/nodes/SeRanking/projectApi/operations/UrlTagsOperations.js +4 -4
  25. package/dist/nodes/SeRanking/projectApi/operations/WebsiteAuditOperations.js +57 -16
  26. package/dist/nodes/SeRanking/utils/apiRequest.js +6 -30
  27. package/package.json +3 -4
  28. package/dist/credentials/SeRankingProjectApi.credentials.d.ts +0 -9
  29. package/dist/credentials/SeRankingProjectApi.credentials.js +0 -39
package/README.md CHANGED
@@ -89,9 +89,10 @@ Open `http://localhost:5678` and add the SE Ranking node to your workflow.
89
89
  ### Step 4: Configure Credentials
90
90
 
91
91
  1. Add SE Ranking node
92
- 2. Click "Create New Credential" for **SE Ranking API** (Data API) — enter your Data API token
93
- 3. (Optional) Click "Create New Credential" for **SE Ranking Project API** — enter your Project API token
94
- 4. Save
92
+ 2. Click "Create New Credential" for **SE Ranking API** — enter your API token
93
+ 3. Save
94
+
95
+ > **v2.0.0 note:** SE Ranking unified its two APIs (Data API + Project API) onto a single host (`api.seranking.com`) with a single token in 2026-05. The node now uses one credential type for everything. If you're upgrading from v1.x, see the Migration section below.
95
96
 
96
97
  ### Docker Installation
97
98
 
@@ -156,19 +157,25 @@ Then restart n8n
156
157
 
157
158
  To use this node, you need:
158
159
 
159
- 1. **SE Ranking Account** - Sign up at [seranking.com](https://seranking.com/)
160
- 2. **API Token** - Generate from your [SE Ranking API Dashboard](https://online.seranking.com/admin.api.dashboard.html)
160
+ 1. **SE Ranking Account** Sign up at [seranking.com](https://seranking.com/)
161
+ 2. **API Token** Generate from your [SE Ranking API Dashboard](https://online.seranking.com/admin.api.dashboard.html)
161
162
 
162
163
  ### Setting up credentials in n8n
163
164
 
164
165
  1. Open any workflow and add the **SE Ranking** node
165
- 2. In the **SE Ranking API** credential slot, click "Create New Credential" and enter your **Data API token** — required for all Data API resources
166
- 3. In the **SE Ranking Project API** credential slot, click "Create New Credential" and enter your **Project API token** — only needed for Project API resources
167
- 4. Click **Save**
166
+ 2. In the **SE Ranking API** credential slot, click "Create New Credential" and enter your API token
167
+ 3. Click **Save** the credential is tested by hitting `GET /v1/account/subscription`
168
+
169
+ ### Migrating from v1.x
170
+
171
+ v1.x used two separate credential types (`seRankingApi` for Data API and `seRankingProjectApi` for Project API) with two different base URLs and two different tokens. As of v2.0.0:
168
172
 
169
- Each credential is tested independently when saved. The node automatically routes requests to the correct API and credential based on the resource you select.
173
+ - One credential type covers everything: **SE Ranking API**
174
+ - One token works against all endpoints — get the unified token from the [API Dashboard](https://online.seranking.com/admin.api.dashboard.html)
175
+ - Old base URL `api4.seranking.com` is deprecated; everything now lives under `api.seranking.com/v1`
176
+ - Project API endpoints moved under `/v1/project-management/...` path prefix
170
177
 
171
- > **Note:** Data API and Project API use different tokens. Data API tokens are UUID format; Project API tokens are 40-character hex format. Get both from your [SE Ranking API Dashboard](https://online.seranking.com/admin.api.dashboard.html).
178
+ If you're upgrading and have saved credentials of type `seRankingProjectApi`, you'll need to re-save them as `seRankingApi` on each affected node. The v1.5.13 release is preserved on npm for rollback (`npm install @seranking/n8n-nodes-seranking@1.5.13`).
172
179
 
173
180
  ---
174
181
 
@@ -5,7 +5,7 @@ class SeRankingApi {
5
5
  constructor() {
6
6
  this.name = 'seRankingApi';
7
7
  this.displayName = 'SE Ranking API';
8
- this.documentationUrl = 'https://seranking.com/api-google-organic.html';
8
+ this.documentationUrl = 'https://seranking.com/api/';
9
9
  this.properties = [
10
10
  {
11
11
  displayName: 'API Token',
@@ -16,7 +16,7 @@ class SeRankingApi {
16
16
  },
17
17
  default: '',
18
18
  required: true,
19
- description: 'Your SE Ranking Data API token from the API Dashboard',
19
+ description: 'Your SE Ranking API token from the API Dashboard. As of 2026-05 a single unified token authenticates both Data API and Project API endpoints.',
20
20
  },
21
21
  ];
22
22
  this.authenticate = {
@@ -1,5 +1,10 @@
1
- import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
1
+ import { IExecuteFunctions, ILoadOptionsFunctions, INodeExecutionData, INodePropertyOptions, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
2
  export declare class SeRanking implements INodeType {
3
3
  description: INodeTypeDescription;
4
+ methods: {
5
+ loadOptions: {
6
+ getAuditIssueCodes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]>;
7
+ };
8
+ };
4
9
  execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
10
  }
@@ -11,6 +11,7 @@ const SerpClassicDescription_1 = require("./dataApi/descriptions/SerpClassicDesc
11
11
  const ProjectManagementDescription_1 = require("./projectApi/descriptions/ProjectManagementDescription");
12
12
  const ProjectGroupsDescription_1 = require("./projectApi/descriptions/ProjectGroupsDescription");
13
13
  const AiResultTrackerDescription_1 = require("./projectApi/descriptions/AiResultTrackerDescription");
14
+ const AirtGroupsDescription_1 = require("./projectApi/descriptions/AirtGroupsDescription");
14
15
  const KeywordGroupsDescription_1 = require("./projectApi/descriptions/KeywordGroupsDescription");
15
16
  const CompetitorsDescription_1 = require("./projectApi/descriptions/CompetitorsDescription");
16
17
  const UrlTagsDescription_1 = require("./projectApi/descriptions/UrlTagsDescription");
@@ -31,6 +32,7 @@ const SerpClassicOperations_1 = require("./dataApi/operations/SerpClassicOperati
31
32
  const ProjectManagementOperations_1 = require("./projectApi/operations/ProjectManagementOperations");
32
33
  const ProjectGroupsOperations_1 = require("./projectApi/operations/ProjectGroupsOperations");
33
34
  const AiResultTrackerOperations_1 = require("./projectApi/operations/AiResultTrackerOperations");
35
+ const AirtGroupsOperations_1 = require("./projectApi/operations/AirtGroupsOperations");
34
36
  const KeywordGroupsOperations_1 = require("./projectApi/operations/KeywordGroupsOperations");
35
37
  const CompetitorsOperations_1 = require("./projectApi/operations/CompetitorsOperations");
36
38
  const UrlTagsOperations_1 = require("./projectApi/operations/UrlTagsOperations");
@@ -62,42 +64,6 @@ class SeRanking {
62
64
  {
63
65
  name: 'seRankingApi',
64
66
  required: true,
65
- displayOptions: {
66
- show: {
67
- resource: [
68
- 'aiSearch',
69
- 'backlinks',
70
- 'domainAnalysis',
71
- 'keywordResearch',
72
- 'serpClassic',
73
- 'websiteAudit',
74
- ],
75
- },
76
- },
77
- },
78
- {
79
- name: 'seRankingProjectApi',
80
- required: true,
81
- displayOptions: {
82
- show: {
83
- resource: [
84
- 'accountSystem',
85
- 'aiResultTracker',
86
- 'analyticsTraffic',
87
- 'backlinkChecker',
88
- 'competitors',
89
- 'generalData',
90
- 'keywordGroups',
91
- 'marketingPlan',
92
- 'projectGroups',
93
- 'projectManagement',
94
- 'searchVolume',
95
- 'subAccount',
96
- 'urlTags',
97
- 'websiteAuditProject',
98
- ],
99
- },
100
- },
101
67
  },
102
68
  ],
103
69
  properties: [
@@ -117,6 +83,11 @@ class SeRanking {
117
83
  value: 'aiResultTracker',
118
84
  description: 'Track brand visibility across AI search engines',
119
85
  },
86
+ {
87
+ name: 'AIRT Groups',
88
+ value: 'airtGroups',
89
+ description: 'Manage AI Result Tracker prompt groups',
90
+ },
120
91
  {
121
92
  name: 'AI Search',
122
93
  value: 'aiSearch',
@@ -228,6 +199,8 @@ class SeRanking {
228
199
  ...ProjectGroupsDescription_1.projectGroupsFields,
229
200
  ...AiResultTrackerDescription_1.aiResultTrackerOperations,
230
201
  ...AiResultTrackerDescription_1.aiResultTrackerFields,
202
+ ...AirtGroupsDescription_1.airtGroupsOperations,
203
+ ...AirtGroupsDescription_1.airtGroupsFields,
231
204
  ...KeywordGroupsDescription_1.keywordGroupsOperations,
232
205
  ...KeywordGroupsDescription_1.keywordGroupsFields,
233
206
  ...CompetitorsDescription_1.competitorsOperations,
@@ -252,6 +225,35 @@ class SeRanking {
252
225
  ...SearchVolumeDescription_1.searchVolumeFields,
253
226
  ],
254
227
  };
228
+ this.methods = {
229
+ loadOptions: {
230
+ async getAuditIssueCodes() {
231
+ const auditId = this.getCurrentNodeParameter('auditId');
232
+ if (!auditId) {
233
+ return [];
234
+ }
235
+ const response = await this.helpers.httpRequestWithAuthentication.call(this, 'seRankingApi', {
236
+ method: 'GET',
237
+ url: 'https://api.seranking.com/v1/project-management/audits/report',
238
+ qs: { audit_id: auditId },
239
+ json: true,
240
+ });
241
+ const codes = new Set();
242
+ const sections = (response && response.sections) || [];
243
+ for (const section of sections) {
244
+ const props = section && section.props;
245
+ if (props && typeof props === 'object') {
246
+ for (const key of Object.keys(props)) {
247
+ codes.add(key);
248
+ }
249
+ }
250
+ }
251
+ return Array.from(codes)
252
+ .sort()
253
+ .map((code) => ({ name: code, value: code }));
254
+ },
255
+ },
256
+ };
255
257
  }
256
258
  async execute() {
257
259
  const items = this.getInputData();
@@ -288,6 +290,9 @@ class SeRanking {
288
290
  case 'aiResultTracker':
289
291
  responseData = await AiResultTrackerOperations_1.AiResultTrackerOperations.call(this, i);
290
292
  break;
293
+ case 'airtGroups':
294
+ responseData = await AirtGroupsOperations_1.AirtGroupsOperations.call(this, i);
295
+ break;
291
296
  case 'keywordGroups':
292
297
  responseData = await KeywordGroupsOperations_1.KeywordGroupsOperations.call(this, i);
293
298
  break;
@@ -429,6 +429,17 @@ exports.aiResultTrackerFields = [
429
429
  default: 0,
430
430
  description: 'Offset from the beginning of the list',
431
431
  },
432
+ {
433
+ displayName: 'Mode',
434
+ name: 'mode',
435
+ type: 'options',
436
+ options: [
437
+ { name: 'Per Prompt (Default)', value: '' },
438
+ { name: 'Aggregated by Group', value: 'groups' },
439
+ ],
440
+ default: '',
441
+ description: 'Set to "groups" to get aggregated time-series per prompt group (mention_presence/link_presence as percentages) instead of per-prompt rankings',
442
+ },
432
443
  ],
433
444
  },
434
445
  {
@@ -0,0 +1,3 @@
1
+ import { INodeProperties } from 'n8n-workflow';
2
+ export declare const airtGroupsOperations: INodeProperties[];
3
+ export declare const airtGroupsFields: INodeProperties[];
@@ -0,0 +1,231 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.airtGroupsFields = exports.airtGroupsOperations = void 0;
4
+ exports.airtGroupsOperations = [
5
+ {
6
+ displayName: 'Operation',
7
+ name: 'operation',
8
+ type: 'options',
9
+ noDataExpression: true,
10
+ displayOptions: {
11
+ show: {
12
+ resource: ['airtGroups'],
13
+ },
14
+ },
15
+ options: [
16
+ {
17
+ name: 'Change Group Order',
18
+ value: 'changeGroupOrder',
19
+ description: 'Move a group to a new position in the site group order',
20
+ action: 'Change prompt group order',
21
+ },
22
+ {
23
+ name: 'Create Prompt Group',
24
+ value: 'createPromptGroup',
25
+ description: 'Create a new prompt group for a site',
26
+ action: 'Create prompt group',
27
+ },
28
+ {
29
+ name: 'Delete All Prompts in Group',
30
+ value: 'deleteAllPromptsInGroup',
31
+ description: 'Remove every prompt currently assigned to the group (group itself is kept)',
32
+ action: 'Delete all prompts in group',
33
+ },
34
+ {
35
+ name: 'Delete Prompt Group',
36
+ value: 'deletePromptGroup',
37
+ description: 'Delete a prompt group; its prompts move to the default group',
38
+ action: 'Delete prompt group',
39
+ },
40
+ {
41
+ name: 'List Prompt Groups',
42
+ value: 'listPromptGroups',
43
+ description: 'List prompt groups for a site, optionally filtered by LLM engine',
44
+ action: 'List prompt groups',
45
+ },
46
+ {
47
+ name: 'Move All Prompts Between Groups',
48
+ value: 'moveAllPromptsBetweenGroups',
49
+ description: 'Move every prompt from one group to another',
50
+ action: 'Move all prompts between groups',
51
+ },
52
+ {
53
+ name: 'Move Prompts to Group',
54
+ value: 'movePromptsToGroup',
55
+ description: 'Move a specific set of prompts into a target group',
56
+ action: 'Move prompts to group',
57
+ },
58
+ {
59
+ name: 'Rename Prompt Group',
60
+ value: 'renamePromptGroup',
61
+ description: 'Update the name of an existing prompt group',
62
+ action: 'Rename prompt group',
63
+ },
64
+ ],
65
+ default: 'listPromptGroups',
66
+ },
67
+ ];
68
+ exports.airtGroupsFields = [
69
+ {
70
+ displayName: 'Site ID',
71
+ name: 'siteId',
72
+ type: 'number',
73
+ required: true,
74
+ displayOptions: {
75
+ show: {
76
+ resource: ['airtGroups'],
77
+ },
78
+ },
79
+ default: 0,
80
+ description: 'Unique project (site) ID',
81
+ },
82
+ {
83
+ displayName: 'Group ID',
84
+ name: 'groupId',
85
+ type: 'number',
86
+ required: true,
87
+ displayOptions: {
88
+ show: {
89
+ resource: ['airtGroups'],
90
+ operation: [
91
+ 'renamePromptGroup',
92
+ 'deletePromptGroup',
93
+ 'changeGroupOrder',
94
+ 'deleteAllPromptsInGroup',
95
+ 'movePromptsToGroup',
96
+ ],
97
+ },
98
+ },
99
+ default: 0,
100
+ description: 'Prompt group ID',
101
+ },
102
+ {
103
+ displayName: 'Group Name',
104
+ name: 'groupName',
105
+ type: 'string',
106
+ required: true,
107
+ displayOptions: {
108
+ show: {
109
+ resource: ['airtGroups'],
110
+ operation: ['createPromptGroup'],
111
+ },
112
+ },
113
+ default: '',
114
+ placeholder: 'Brand queries',
115
+ description: 'Non-empty, max 255 characters, unique within the site',
116
+ },
117
+ {
118
+ displayName: 'New Group Name',
119
+ name: 'groupName',
120
+ type: 'string',
121
+ required: true,
122
+ displayOptions: {
123
+ show: {
124
+ resource: ['airtGroups'],
125
+ operation: ['renamePromptGroup'],
126
+ },
127
+ },
128
+ default: '',
129
+ placeholder: 'Updated group name',
130
+ description: 'New name for the prompt group; non-empty, max 255 characters',
131
+ },
132
+ {
133
+ displayName: 'Place Before Group ID',
134
+ name: 'beforeId',
135
+ type: 'number',
136
+ displayOptions: {
137
+ show: {
138
+ resource: ['airtGroups'],
139
+ operation: ['changeGroupOrder'],
140
+ },
141
+ },
142
+ default: 0,
143
+ description: 'Place the group immediately before this neighbour. Provide exactly ONE of Before or After — leave the other at 0',
144
+ },
145
+ {
146
+ displayName: 'Place After Group ID',
147
+ name: 'afterId',
148
+ type: 'number',
149
+ displayOptions: {
150
+ show: {
151
+ resource: ['airtGroups'],
152
+ operation: ['changeGroupOrder'],
153
+ },
154
+ },
155
+ default: 0,
156
+ description: 'Place the group immediately after this neighbour. Provide exactly ONE of Before or After — leave the other at 0',
157
+ },
158
+ {
159
+ displayName: 'Keyword-LLM Link IDs',
160
+ name: 'k2siteLlmIds',
161
+ type: 'string',
162
+ required: true,
163
+ displayOptions: {
164
+ show: {
165
+ resource: ['airtGroups'],
166
+ operation: ['movePromptsToGroup'],
167
+ },
168
+ },
169
+ default: '',
170
+ placeholder: '2164555,2164556,2164557',
171
+ description: 'Comma-separated list of integer k2site_llm_id values (from List Prompts)',
172
+ },
173
+ {
174
+ displayName: 'Source Group ID',
175
+ name: 'fromGroupId',
176
+ type: 'number',
177
+ required: true,
178
+ displayOptions: {
179
+ show: {
180
+ resource: ['airtGroups'],
181
+ operation: ['moveAllPromptsBetweenGroups'],
182
+ },
183
+ },
184
+ default: 0,
185
+ description: 'Group whose prompts will be moved',
186
+ },
187
+ {
188
+ displayName: 'Target Group ID',
189
+ name: 'toGroupId',
190
+ type: 'number',
191
+ required: true,
192
+ displayOptions: {
193
+ show: {
194
+ resource: ['airtGroups'],
195
+ operation: ['moveAllPromptsBetweenGroups'],
196
+ },
197
+ },
198
+ default: 0,
199
+ description: 'Destination group; must differ from Source Group ID',
200
+ },
201
+ {
202
+ displayName: 'Additional Fields',
203
+ name: 'additionalFields',
204
+ type: 'collection',
205
+ placeholder: 'Add Field',
206
+ default: {},
207
+ displayOptions: {
208
+ show: {
209
+ resource: ['airtGroups'],
210
+ operation: ['listPromptGroups'],
211
+ },
212
+ },
213
+ options: [
214
+ {
215
+ displayName: 'Include Prompt Counts',
216
+ name: 'keysCount',
217
+ type: 'boolean',
218
+ default: false,
219
+ description: 'Whether to include keys_count on every group',
220
+ },
221
+ {
222
+ displayName: 'Filter by Site LLM IDs',
223
+ name: 'siteLlmIds',
224
+ type: 'string',
225
+ default: '',
226
+ placeholder: '1130467,1130468',
227
+ description: 'Comma-separated list of site_llm_id values to filter groups by',
228
+ },
229
+ ],
230
+ },
231
+ ];
@@ -187,6 +187,18 @@ exports.projectManagementOperations = [
187
187
  description: 'Set a ranking position for a keyword on a date',
188
188
  action: 'Set manual keyword position',
189
189
  },
190
+ {
191
+ name: 'List Check Dates',
192
+ value: 'listCheckDates',
193
+ description: 'Get actual ranking check dates for a project',
194
+ action: 'List check dates',
195
+ },
196
+ {
197
+ name: 'Get Ranking Trends',
198
+ value: 'getRankingTrends',
199
+ description: 'Get ranking trend time series (avg position, visibility, top10)',
200
+ action: 'Get ranking trends',
201
+ },
190
202
  ],
191
203
  default: 'listProjects',
192
204
  },
@@ -216,6 +228,8 @@ exports.projectManagementFields = [
216
228
  'deleteKeywords',
217
229
  'setManualPosition',
218
230
  'runRecheck',
231
+ 'listCheckDates',
232
+ 'getRankingTrends',
219
233
  ],
220
234
  },
221
235
  },
@@ -807,4 +821,117 @@ exports.projectManagementFields = [
807
821
  default: '[{"site_engine_id":1,"keyword_id":2}]',
808
822
  description: 'JSON array of objects: { site_engine_id, keyword_id }',
809
823
  },
824
+ {
825
+ displayName: 'Additional Fields',
826
+ name: 'additionalFields',
827
+ type: 'collection',
828
+ placeholder: 'Add Field',
829
+ default: {},
830
+ displayOptions: {
831
+ show: {
832
+ resource: ['projectManagement'],
833
+ operation: ['listCheckDates'],
834
+ },
835
+ },
836
+ options: [
837
+ {
838
+ displayName: 'Site Engine ID',
839
+ name: 'siteEngineId',
840
+ type: 'number',
841
+ default: 0,
842
+ description: 'Limit to a single search engine',
843
+ },
844
+ {
845
+ displayName: 'Date From',
846
+ name: 'dateFrom',
847
+ type: 'string',
848
+ default: '',
849
+ placeholder: '2026-01-01',
850
+ description: 'Start date (YYYY-MM-DD). Defaults to 7 days ago.',
851
+ },
852
+ {
853
+ displayName: 'Date To',
854
+ name: 'dateTo',
855
+ type: 'string',
856
+ default: '',
857
+ placeholder: '2026-01-31',
858
+ description: 'End date (YYYY-MM-DD). Defaults to today.',
859
+ },
860
+ ],
861
+ },
862
+ {
863
+ displayName: 'Additional Fields',
864
+ name: 'additionalFields',
865
+ type: 'collection',
866
+ placeholder: 'Add Field',
867
+ default: {},
868
+ displayOptions: {
869
+ show: {
870
+ resource: ['projectManagement'],
871
+ operation: ['getRankingTrends'],
872
+ },
873
+ },
874
+ options: [
875
+ {
876
+ displayName: 'Site Engine ID',
877
+ name: 'siteEngineId',
878
+ type: 'number',
879
+ default: 0,
880
+ description: 'Limit to a single search engine (drops the cross-engine average row)',
881
+ },
882
+ {
883
+ displayName: 'Date From',
884
+ name: 'dateFrom',
885
+ type: 'string',
886
+ default: '',
887
+ placeholder: '2026-01-01',
888
+ description: 'Start date (YYYY-MM-DD). Defaults to 7 days ago.',
889
+ },
890
+ {
891
+ displayName: 'Date To',
892
+ name: 'dateTo',
893
+ type: 'string',
894
+ default: '',
895
+ placeholder: '2026-01-31',
896
+ description: 'End date (YYYY-MM-DD). Defaults to today.',
897
+ },
898
+ {
899
+ displayName: 'Metric Type',
900
+ name: 'metricType',
901
+ type: 'options',
902
+ options: [
903
+ { name: 'Average Position', value: 'avg_pos' },
904
+ { name: 'Visibility (Raw Score)', value: 'visibility' },
905
+ { name: 'Visibility (%)', value: 'visibility_percent' },
906
+ { name: 'Top 10 (Count)', value: 'top10' },
907
+ { name: 'Top 10 (%)', value: 'top10_percent' },
908
+ ],
909
+ default: 'avg_pos',
910
+ description: 'Which ranking metric to retrieve',
911
+ },
912
+ {
913
+ displayName: 'Group ID',
914
+ name: 'groupId',
915
+ type: 'number',
916
+ default: 0,
917
+ description: 'Filter to a keyword group',
918
+ },
919
+ {
920
+ displayName: 'Keyword IDs',
921
+ name: 'keywordsIds',
922
+ type: 'string',
923
+ default: '',
924
+ placeholder: '123,456,789',
925
+ description: 'Comma-separated keyword IDs to filter',
926
+ },
927
+ {
928
+ displayName: 'Tag IDs',
929
+ name: 'tagsIds',
930
+ type: 'string',
931
+ default: '',
932
+ placeholder: '1,2,3',
933
+ description: 'Comma-separated landing-page tag IDs to filter',
934
+ },
935
+ ],
936
+ },
810
937
  ];