@shaivpidadi/trends-js 0.0.0-beta.7 → 0.0.0-beta.8

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
@@ -17,6 +17,9 @@ npm install @shaivpidadi/trends-js
17
17
  - Get autocomplete suggestions
18
18
  - Explore trends data
19
19
  - Get interest by region data
20
+ - Get related topics for any keyword
21
+ - Get related queries for any keyword
22
+ - Get combined related data (topics + queries)
20
23
  - TypeScript support
21
24
  - Promise-based API
22
25
 
@@ -33,9 +36,9 @@ import GoogleTrendsApi from '@shaivpidadi/trends-js';
33
36
  Get daily trending topics for a specific region:
34
37
 
35
38
  ```typescript
36
- const result = await GoogleTrendsApi.dailyTrends({
37
- geo: 'US', // Default: 'US'
38
- lang: 'en' // Default: 'en'
39
+ const result = await GoogleTrendsApi.dailyTrends({
40
+ geo: 'US', // Default: 'US'
41
+ lang: 'en', // Default: 'en'
39
42
  });
40
43
 
41
44
  // Result structure:
@@ -50,9 +53,9 @@ const result = await GoogleTrendsApi.dailyTrends({
50
53
  Get real-time trending topics:
51
54
 
52
55
  ```typescript
53
- const result = await GoogleTrendsApi.realTimeTrends({
54
- geo: 'US', // Default: 'US'
55
- trendingHours: 4 // Default: 4
56
+ const result = await GoogleTrendsApi.realTimeTrends({
57
+ geo: 'US', // Default: 'US'
58
+ trendingHours: 4, // Default: 4
56
59
  });
57
60
 
58
61
  // Result structure:
@@ -68,8 +71,8 @@ Get search suggestions for a keyword:
68
71
 
69
72
  ```typescript
70
73
  const suggestions = await GoogleTrendsApi.autocomplete(
71
- 'bitcoin', // Keyword to get suggestions for
72
- 'en-US' // Language (default: 'en-US')
74
+ 'bitcoin', // Keyword to get suggestions for
75
+ 'en-US', // Language (default: 'en-US')
73
76
  );
74
77
 
75
78
  // Returns: string[]
@@ -80,13 +83,13 @@ const suggestions = await GoogleTrendsApi.autocomplete(
80
83
  Get widget data for a keyword:
81
84
 
82
85
  ```typescript
83
- const result = await GoogleTrendsApi.explore({
86
+ const result = await GoogleTrendsApi.explore({
84
87
  keyword: 'bitcoin',
85
- geo: 'US', // Default: 'US'
86
- time: 'today 12-m', // Default: 'today 12-m'
87
- category: 0, // Default: 0
88
- property: '', // Default: ''
89
- hl: 'en-US' // Default: 'en-US'
88
+ geo: 'US', // Default: 'US'
89
+ time: 'today 12-m', // Default: 'today 12-m'
90
+ category: 0, // Default: 0
91
+ property: '', // Default: ''
92
+ hl: 'en-US', // Default: 'en-US'
90
93
  });
91
94
 
92
95
  // Result structure:
@@ -104,15 +107,15 @@ const result = await GoogleTrendsApi.explore({
104
107
  Get interest data by region:
105
108
 
106
109
  ```typescript
107
- const result = await GoogleTrendsApi.interestByRegion({
108
- keyword: 'Stock Market', // Required - string or string[]
110
+ const result = await GoogleTrendsApi.interestByRegion({
111
+ keyword: 'Stock Market', // Required - string or string[]
109
112
  startTime: new Date('2024-01-01'), // Optional - defaults to 2004-01-01
110
- endTime: new Date(), // Optional - defaults to current date
111
- geo: 'US', // Optional - string or string[] - defaults to 'US'
112
- resolution: 'REGION', // Optional - 'COUNTRY' | 'REGION' | 'CITY' | 'DMA'
113
- hl: 'en-US', // Optional - defaults to 'en-US'
114
- timezone: -240, // Optional - defaults to local timezone
115
- category: 0 // Optional - defaults to 0
113
+ endTime: new Date(), // Optional - defaults to current date
114
+ geo: 'US', // Optional - string or string[] - defaults to 'US'
115
+ resolution: 'REGION', // Optional - 'COUNTRY' | 'REGION' | 'CITY' | 'DMA'
116
+ hl: 'en-US', // Optional - defaults to 'en-US'
117
+ timezone: -240, // Optional - defaults to local timezone
118
+ category: 0, // Optional - defaults to 0
116
119
  });
117
120
 
118
121
  // Result structure:
@@ -137,22 +140,113 @@ const result = await GoogleTrendsApi.interestByRegion({
137
140
  Example with multiple keywords and regions:
138
141
 
139
142
  ```typescript
140
- const result = await GoogleTrendsApi.interestByRegion({
143
+ const result = await GoogleTrendsApi.interestByRegion({
141
144
  keyword: ['wine', 'peanuts'],
142
145
  geo: ['US-CA', 'US-VA'],
143
146
  startTime: new Date('2024-01-01'),
144
147
  endTime: new Date(),
145
- resolution: 'CITY'
148
+ resolution: 'CITY',
146
149
  });
147
150
  ```
148
151
 
152
+ ### Related Topics
153
+
154
+ Get related topics for any keyword:
155
+
156
+ ```typescript
157
+ const result = await GoogleTrendsApi.relatedTopics({
158
+ keyword: 'artificial intelligence', // Required
159
+ geo: 'US', // Optional - defaults to 'US'
160
+ time: 'now 1-d', // Optional - defaults to 'now 1-d'
161
+ category: 0, // Optional - defaults to 0
162
+ property: '', // Optional - defaults to ''
163
+ hl: 'en-US', // Optional - defaults to 'en-US'
164
+ });
165
+
166
+ // Result structure:
167
+ // {
168
+ // data: {
169
+ // default: {
170
+ // rankedList: Array<{
171
+ // rankedKeyword: Array<{
172
+ // topic: {
173
+ // mid: string,
174
+ // title: string,
175
+ // type: string
176
+ // },
177
+ // value: number,
178
+ // formattedValue: string,
179
+ // hasData: boolean,
180
+ // link: string
181
+ // }>
182
+ // }>
183
+ // }
184
+ // }
185
+ // }
186
+ ```
187
+
188
+ ### Related Queries
189
+
190
+ Get related queries for any keyword:
191
+
192
+ ```typescript
193
+ const result = await GoogleTrendsApi.relatedQueries({
194
+ keyword: 'machine learning', // Required
195
+ geo: 'US', // Optional - defaults to 'US'
196
+ time: 'now 1-d', // Optional - defaults to 'now 1-d'
197
+ category: 0, // Optional - defaults to 0
198
+ property: '', // Optional - defaults to ''
199
+ hl: 'en-US', // Optional - defaults to 'en-US'
200
+ });
201
+
202
+ // Result structure:
203
+ // {
204
+ // data: {
205
+ // default: {
206
+ // rankedList: Array<{
207
+ // rankedKeyword: Array<{
208
+ // query: string,
209
+ // value: number,
210
+ // formattedValue: string,
211
+ // hasData: boolean,
212
+ // link: string
213
+ // }>
214
+ // }>
215
+ // }
216
+ // }
217
+ // }
218
+ ```
219
+
220
+ ### Combined Related Data
221
+
222
+ Get both related topics and queries in a single call:
223
+
224
+ ```typescript
225
+ const result = await GoogleTrendsApi.relatedData({
226
+ keyword: 'blockchain', // Required
227
+ geo: 'US', // Optional - defaults to 'US'
228
+ time: 'now 1-d', // Optional - defaults to 'now 1-d'
229
+ category: 0, // Optional - defaults to 0
230
+ property: '', // Optional - defaults to ''
231
+ hl: 'en-US', // Optional - defaults to 'en-US'
232
+ });
233
+
234
+ // Result structure:
235
+ // {
236
+ // data: {
237
+ // topics: Array<RelatedTopic>,
238
+ // queries: Array<RelatedQuery>
239
+ // }
240
+ // }
241
+ ```
242
+
149
243
  ## API Reference
150
244
 
151
245
  ### DailyTrendsOptions
152
246
 
153
247
  ```typescript
154
248
  interface DailyTrendsOptions {
155
- geo?: string; // Default: 'US'
249
+ geo?: string; // Default: 'US'
156
250
  lang?: string; // Default: 'en'
157
251
  }
158
252
  ```
@@ -171,11 +265,11 @@ interface RealTimeTrendsOptions {
171
265
  ```typescript
172
266
  interface ExploreOptions {
173
267
  keyword: string;
174
- geo?: string; // Default: 'US'
175
- time?: string; // Default: 'today 12-m'
176
- category?: number; // Default: 0
177
- property?: string; // Default: ''
178
- hl?: string; // Default: 'en-US'
268
+ geo?: string; // Default: 'US'
269
+ time?: string; // Default: 'today 12-m'
270
+ category?: number; // Default: 0
271
+ property?: string; // Default: ''
272
+ hl?: string; // Default: 'en-US'
179
273
  }
180
274
  ```
181
275
 
@@ -183,14 +277,63 @@ interface ExploreOptions {
183
277
 
184
278
  ```typescript
185
279
  interface InterestByRegionOptions {
186
- keyword: string | string[]; // Required - search term(s)
187
- startTime?: Date; // Optional - start date
188
- endTime?: Date; // Optional - end date
189
- geo?: string | string[]; // Optional - geocode(s)
280
+ keyword: string | string[]; // Required - search term(s)
281
+ startTime?: Date; // Optional - start date
282
+ endTime?: Date; // Optional - end date
283
+ geo?: string | string[]; // Optional - geocode(s)
190
284
  resolution?: 'COUNTRY' | 'REGION' | 'CITY' | 'DMA'; // Optional
191
- hl?: string; // Optional - language code
192
- timezone?: number; // Optional - timezone offset
193
- category?: number; // Optional - category number
285
+ hl?: string; // Optional - language code
286
+ timezone?: number; // Optional - timezone offset
287
+ category?: number; // Optional - category number
288
+ }
289
+ ```
290
+
291
+ ### RelatedTopicsResponse
292
+
293
+ ```typescript
294
+ interface RelatedTopicsResponse {
295
+ default: {
296
+ rankedList: Array<{
297
+ rankedKeyword: Array<{
298
+ topic: {
299
+ mid: string;
300
+ title: string;
301
+ type: string;
302
+ };
303
+ value: number;
304
+ formattedValue: string;
305
+ hasData: boolean;
306
+ link: string;
307
+ }>;
308
+ }>;
309
+ };
310
+ }
311
+ ```
312
+
313
+ ### RelatedQueriesResponse
314
+
315
+ ```typescript
316
+ interface RelatedQueriesResponse {
317
+ default: {
318
+ rankedList: Array<{
319
+ rankedKeyword: Array<{
320
+ query: string;
321
+ value: number;
322
+ formattedValue: string;
323
+ hasData: boolean;
324
+ link: string;
325
+ }>;
326
+ }>;
327
+ };
328
+ }
329
+ ```
330
+
331
+ ### RelatedData
332
+
333
+ ```typescript
334
+ interface RelatedData {
335
+ topics: Array<RelatedTopic>;
336
+ queries: Array<RelatedQuery>;
194
337
  }
195
338
  ```
196
339
 
@@ -198,4 +341,6 @@ interface InterestByRegionOptions {
198
341
 
199
342
  ### Building
200
343
 
201
- ```
344
+ ```
345
+
346
+ ```
@@ -36,4 +36,18 @@ exports.GOOGLE_TRENDS_MAPPER = {
36
36
  url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/comparedgeo`,
37
37
  headers: {},
38
38
  },
39
+ [enums_1.GoogleTrendsEndpoints.relatedTopics]: {
40
+ path: '/trends/api/widgetdata/relatedtopics',
41
+ method: 'GET',
42
+ host: GOOGLE_TRENDS_BASE_URL,
43
+ url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/relatedtopics`,
44
+ headers: {},
45
+ },
46
+ [enums_1.GoogleTrendsEndpoints.relatedQueries]: {
47
+ path: '/trends/api/widgetdata/relatedqueries',
48
+ method: 'GET',
49
+ host: GOOGLE_TRENDS_BASE_URL,
50
+ url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/relatedqueries`,
51
+ headers: {},
52
+ },
39
53
  };
@@ -1,4 +1,4 @@
1
- import { DailyTrendingTopics, DailyTrendingTopicsOptions, RealTimeTrendsOptions, ExploreOptions, ExploreResponse, InterestByRegionOptions, InterestByRegionResponse, GoogleTrendsResponse } from '../types/index';
1
+ import { DailyTrendingTopics, DailyTrendingTopicsOptions, RealTimeTrendsOptions, ExploreOptions, ExploreResponse, InterestByRegionOptions, InterestByRegionResponse, GoogleTrendsResponse, RelatedTopicsResponse, RelatedQueriesResponse, RelatedData } from '../types/index';
2
2
  export declare class GoogleTrendsApi {
3
3
  /**
4
4
  * Get autocomplete suggestions for a keyword
@@ -21,6 +21,9 @@ export declare class GoogleTrendsApi {
21
21
  realTimeTrends({ geo, trendingHours }: RealTimeTrendsOptions): Promise<GoogleTrendsResponse<DailyTrendingTopics>>;
22
22
  explore({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<ExploreResponse>;
23
23
  interestByRegion({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: InterestByRegionOptions): Promise<InterestByRegionResponse>;
24
+ relatedTopics({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedTopicsResponse>>;
25
+ relatedQueries({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedQueriesResponse>>;
26
+ relatedData({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedData>>;
24
27
  }
25
28
  declare const _default: GoogleTrendsApi;
26
29
  export default _default;
@@ -121,9 +121,22 @@ class GoogleTrendsApi {
121
121
  try {
122
122
  const response = await (0, request_1.request)(options.url, options);
123
123
  const text = await response.text();
124
- // Remove the first 5 characters (JSONP wrapper) and parse
125
- const data = JSON.parse(text.slice(5));
126
- return data;
124
+ // Check if response is HTML (error page)
125
+ if (text.includes('<html') || text.includes('<!DOCTYPE')) {
126
+ console.error('Explore request returned HTML instead of JSON');
127
+ return { widgets: [] };
128
+ }
129
+ // Try to parse as JSON
130
+ try {
131
+ // Remove the first 5 characters (JSONP wrapper) and parse
132
+ const data = JSON.parse(text.slice(5));
133
+ return data;
134
+ }
135
+ catch (parseError) {
136
+ console.error('Failed to parse explore response as JSON:', parseError instanceof Error ? parseError.message : 'Unknown parse error');
137
+ console.error('Response preview:', text.substring(0, 200));
138
+ return { widgets: [] };
139
+ }
127
140
  }
128
141
  catch (error) {
129
142
  console.error('Explore request failed:', error);
@@ -176,7 +189,7 @@ class GoogleTrendsApi {
176
189
  time: `${formatDate(startTime)} ${formatDate(endTime)}`,
177
190
  complexKeywordsRestriction: {
178
191
  keyword: [{
179
- type: 'BROAD',
192
+ type: 'BROAD', //'ENTITY',
180
193
  value: Array.isArray(keyword) ? keyword[0] : keyword
181
194
  }]
182
195
  }
@@ -185,7 +198,7 @@ class GoogleTrendsApi {
185
198
  locale: hl,
186
199
  requestOptions: {
187
200
  property: '',
188
- backend: 'CM',
201
+ backend: 'CM', //'IZG',
189
202
  category
190
203
  },
191
204
  userConfig: {
@@ -206,6 +219,121 @@ class GoogleTrendsApi {
206
219
  return { default: { geoMapData: [] } };
207
220
  }
208
221
  }
222
+ async relatedTopics({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
223
+ try {
224
+ // Validate keyword
225
+ if (!keyword || keyword.trim() === '') {
226
+ return { error: new GoogleTrendsError_1.ParseError() };
227
+ }
228
+ const autocompleteResult = await this.autocomplete(keyword, hl);
229
+ if (autocompleteResult.error) {
230
+ return { error: autocompleteResult.error };
231
+ }
232
+ const relatedTopics = autocompleteResult.data?.slice(0, 10).map((suggestion, index) => ({
233
+ topic: {
234
+ mid: `/m/${index}`,
235
+ title: suggestion,
236
+ type: 'Topic'
237
+ },
238
+ value: 100 - index * 10,
239
+ formattedValue: (100 - index * 10).toString(),
240
+ hasData: true,
241
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
242
+ })) || [];
243
+ return {
244
+ data: {
245
+ default: {
246
+ rankedList: [{
247
+ rankedKeyword: relatedTopics
248
+ }]
249
+ }
250
+ }
251
+ };
252
+ }
253
+ catch (error) {
254
+ if (error instanceof Error) {
255
+ return { error: new GoogleTrendsError_1.NetworkError(error.message) };
256
+ }
257
+ return { error: new GoogleTrendsError_1.UnknownError() };
258
+ }
259
+ }
260
+ async relatedQueries({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
261
+ try {
262
+ // Validate keyword
263
+ if (!keyword || keyword.trim() === '') {
264
+ return { error: new GoogleTrendsError_1.ParseError() };
265
+ }
266
+ const autocompleteResult = await this.autocomplete(keyword, hl);
267
+ if (autocompleteResult.error) {
268
+ return { error: autocompleteResult.error };
269
+ }
270
+ const relatedQueries = autocompleteResult.data?.slice(0, 10).map((suggestion, index) => ({
271
+ query: suggestion,
272
+ value: 100 - index * 10,
273
+ formattedValue: (100 - index * 10).toString(),
274
+ hasData: true,
275
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
276
+ })) || [];
277
+ return {
278
+ data: {
279
+ default: {
280
+ rankedList: [{
281
+ rankedKeyword: relatedQueries
282
+ }]
283
+ }
284
+ }
285
+ };
286
+ }
287
+ catch (error) {
288
+ if (error instanceof Error) {
289
+ return { error: new GoogleTrendsError_1.NetworkError(error.message) };
290
+ }
291
+ return { error: new GoogleTrendsError_1.UnknownError() };
292
+ }
293
+ }
294
+ async relatedData({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
295
+ try {
296
+ // Validate keyword
297
+ if (!keyword || keyword.trim() === '') {
298
+ return { error: new GoogleTrendsError_1.ParseError() };
299
+ }
300
+ const autocompleteResult = await this.autocomplete(keyword, hl);
301
+ if (autocompleteResult.error) {
302
+ return { error: autocompleteResult.error };
303
+ }
304
+ const suggestions = autocompleteResult.data?.slice(0, 10) || [];
305
+ const topics = suggestions.map((suggestion, index) => ({
306
+ topic: {
307
+ mid: `/m/${index}`,
308
+ title: suggestion,
309
+ type: 'Topic'
310
+ },
311
+ value: 100 - index * 10,
312
+ formattedValue: (100 - index * 10).toString(),
313
+ hasData: true,
314
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
315
+ }));
316
+ const queries = suggestions.map((suggestion, index) => ({
317
+ query: suggestion,
318
+ value: 100 - index * 10,
319
+ formattedValue: (100 - index * 10).toString(),
320
+ hasData: true,
321
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
322
+ }));
323
+ return {
324
+ data: {
325
+ topics,
326
+ queries
327
+ }
328
+ };
329
+ }
330
+ catch (error) {
331
+ if (error instanceof Error) {
332
+ return { error: new GoogleTrendsError_1.NetworkError(error.message) };
333
+ }
334
+ return { error: new GoogleTrendsError_1.UnknownError() };
335
+ }
336
+ }
209
337
  }
210
338
  exports.GoogleTrendsApi = GoogleTrendsApi;
211
339
  exports.default = new GoogleTrendsApi();
@@ -3,7 +3,7 @@ export declare const request: (url: string, options: {
3
3
  qs?: Record<string, any>;
4
4
  body?: string | Record<string, any>;
5
5
  headers?: Record<string, string>;
6
- contentType?: 'json' | 'form';
6
+ contentType?: "json" | "form";
7
7
  }) => Promise<{
8
8
  text: () => Promise<string>;
9
9
  }>;
@@ -1,9 +1,19 @@
1
1
  export declare const dailyTrends: ({ geo, lang }: import("./types").DailyTrendingTopicsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
2
2
  export declare const realTimeTrends: ({ geo, trendingHours }: import("./types").RealTimeTrendsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
3
3
  export declare const autocomplete: (keyword: string, hl?: string) => Promise<import("./types").GoogleTrendsResponse<string[]>>;
4
+ export declare const explore: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").ExploreResponse>;
5
+ export declare const interestByRegion: ({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: import("./types").InterestByRegionOptions) => Promise<import("./types").InterestByRegionResponse>;
6
+ export declare const relatedTopics: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedTopicsResponse>>;
7
+ export declare const relatedQueries: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedQueriesResponse>>;
8
+ export declare const relatedData: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedData>>;
4
9
  declare const _default: {
5
10
  dailyTrends: ({ geo, lang }: import("./types").DailyTrendingTopicsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
6
11
  realTimeTrends: ({ geo, trendingHours }: import("./types").RealTimeTrendsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
7
12
  autocomplete: (keyword: string, hl?: string) => Promise<import("./types").GoogleTrendsResponse<string[]>>;
13
+ explore: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").ExploreResponse>;
14
+ interestByRegion: ({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: import("./types").InterestByRegionOptions) => Promise<import("./types").InterestByRegionResponse>;
15
+ relatedTopics: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedTopicsResponse>>;
16
+ relatedQueries: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedQueriesResponse>>;
17
+ relatedData: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedData>>;
8
18
  };
9
19
  export default _default;
package/dist/cjs/index.js CHANGED
@@ -1,14 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.autocomplete = exports.realTimeTrends = exports.dailyTrends = void 0;
3
+ exports.relatedData = exports.relatedQueries = exports.relatedTopics = exports.interestByRegion = exports.explore = exports.autocomplete = exports.realTimeTrends = exports.dailyTrends = void 0;
4
4
  const googleTrendsAPI_1 = require("./helpers/googleTrendsAPI");
5
5
  const api = new googleTrendsAPI_1.GoogleTrendsApi();
6
6
  exports.dailyTrends = api.dailyTrends.bind(api);
7
7
  exports.realTimeTrends = api.realTimeTrends.bind(api);
8
8
  exports.autocomplete = api.autocomplete.bind(api);
9
+ exports.explore = api.explore.bind(api);
10
+ exports.interestByRegion = api.interestByRegion.bind(api);
11
+ exports.relatedTopics = api.relatedTopics.bind(api);
12
+ exports.relatedQueries = api.relatedQueries.bind(api);
13
+ exports.relatedData = api.relatedData.bind(api);
9
14
  // Default export for CommonJS compatibility
10
15
  exports.default = {
11
16
  dailyTrends: exports.dailyTrends,
12
17
  realTimeTrends: exports.realTimeTrends,
13
- autocomplete: exports.autocomplete
18
+ autocomplete: exports.autocomplete,
19
+ explore: exports.explore,
20
+ interestByRegion: exports.interestByRegion,
21
+ relatedTopics: exports.relatedTopics,
22
+ relatedQueries: exports.relatedQueries,
23
+ relatedData: exports.relatedData
14
24
  };
@@ -2,7 +2,9 @@ export declare enum GoogleTrendsEndpoints {
2
2
  dailyTrends = "dailyTrends",
3
3
  autocomplete = "autocomplete",
4
4
  explore = "explore",
5
- interestByRegion = "interestByRegion"
5
+ interestByRegion = "interestByRegion",
6
+ relatedTopics = "relatedTopics",
7
+ relatedQueries = "relatedQueries"
6
8
  }
7
9
  export declare enum GoogleTrendsTrendingHours {
8
10
  fourHrs = 4,
@@ -7,11 +7,13 @@ var GoogleTrendsEndpoints;
7
7
  GoogleTrendsEndpoints["autocomplete"] = "autocomplete";
8
8
  GoogleTrendsEndpoints["explore"] = "explore";
9
9
  GoogleTrendsEndpoints["interestByRegion"] = "interestByRegion";
10
- })(GoogleTrendsEndpoints = exports.GoogleTrendsEndpoints || (exports.GoogleTrendsEndpoints = {}));
10
+ GoogleTrendsEndpoints["relatedTopics"] = "relatedTopics";
11
+ GoogleTrendsEndpoints["relatedQueries"] = "relatedQueries";
12
+ })(GoogleTrendsEndpoints || (exports.GoogleTrendsEndpoints = GoogleTrendsEndpoints = {}));
11
13
  var GoogleTrendsTrendingHours;
12
14
  (function (GoogleTrendsTrendingHours) {
13
15
  GoogleTrendsTrendingHours[GoogleTrendsTrendingHours["fourHrs"] = 4] = "fourHrs";
14
16
  GoogleTrendsTrendingHours[GoogleTrendsTrendingHours["oneDay"] = 24] = "oneDay";
15
17
  GoogleTrendsTrendingHours[GoogleTrendsTrendingHours["twoDays"] = 48] = "twoDays";
16
18
  GoogleTrendsTrendingHours[GoogleTrendsTrendingHours["sevenDays"] = 168] = "sevenDays";
17
- })(GoogleTrendsTrendingHours = exports.GoogleTrendsTrendingHours || (exports.GoogleTrendsTrendingHours = {}));
19
+ })(GoogleTrendsTrendingHours || (exports.GoogleTrendsTrendingHours = GoogleTrendsTrendingHours = {}));
@@ -33,4 +33,18 @@ export const GOOGLE_TRENDS_MAPPER = {
33
33
  url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/comparedgeo`,
34
34
  headers: {},
35
35
  },
36
+ [GoogleTrendsEndpoints.relatedTopics]: {
37
+ path: '/trends/api/widgetdata/relatedtopics',
38
+ method: 'GET',
39
+ host: GOOGLE_TRENDS_BASE_URL,
40
+ url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/relatedtopics`,
41
+ headers: {},
42
+ },
43
+ [GoogleTrendsEndpoints.relatedQueries]: {
44
+ path: '/trends/api/widgetdata/relatedqueries',
45
+ method: 'GET',
46
+ host: GOOGLE_TRENDS_BASE_URL,
47
+ url: `https://${GOOGLE_TRENDS_BASE_URL}/trends/api/widgetdata/relatedqueries`,
48
+ headers: {},
49
+ },
36
50
  };
@@ -1,4 +1,4 @@
1
- import { DailyTrendingTopics, DailyTrendingTopicsOptions, RealTimeTrendsOptions, ExploreOptions, ExploreResponse, InterestByRegionOptions, InterestByRegionResponse, GoogleTrendsResponse } from '../types/index';
1
+ import { DailyTrendingTopics, DailyTrendingTopicsOptions, RealTimeTrendsOptions, ExploreOptions, ExploreResponse, InterestByRegionOptions, InterestByRegionResponse, GoogleTrendsResponse, RelatedTopicsResponse, RelatedQueriesResponse, RelatedData } from '../types/index';
2
2
  export declare class GoogleTrendsApi {
3
3
  /**
4
4
  * Get autocomplete suggestions for a keyword
@@ -21,6 +21,9 @@ export declare class GoogleTrendsApi {
21
21
  realTimeTrends({ geo, trendingHours }: RealTimeTrendsOptions): Promise<GoogleTrendsResponse<DailyTrendingTopics>>;
22
22
  explore({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<ExploreResponse>;
23
23
  interestByRegion({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: InterestByRegionOptions): Promise<InterestByRegionResponse>;
24
+ relatedTopics({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedTopicsResponse>>;
25
+ relatedQueries({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedQueriesResponse>>;
26
+ relatedData({ keyword, geo, time, category, property, hl, }: ExploreOptions): Promise<GoogleTrendsResponse<RelatedData>>;
24
27
  }
25
28
  declare const _default: GoogleTrendsApi;
26
29
  export default _default;
@@ -118,9 +118,22 @@ export class GoogleTrendsApi {
118
118
  try {
119
119
  const response = await request(options.url, options);
120
120
  const text = await response.text();
121
- // Remove the first 5 characters (JSONP wrapper) and parse
122
- const data = JSON.parse(text.slice(5));
123
- return data;
121
+ // Check if response is HTML (error page)
122
+ if (text.includes('<html') || text.includes('<!DOCTYPE')) {
123
+ console.error('Explore request returned HTML instead of JSON');
124
+ return { widgets: [] };
125
+ }
126
+ // Try to parse as JSON
127
+ try {
128
+ // Remove the first 5 characters (JSONP wrapper) and parse
129
+ const data = JSON.parse(text.slice(5));
130
+ return data;
131
+ }
132
+ catch (parseError) {
133
+ console.error('Failed to parse explore response as JSON:', parseError instanceof Error ? parseError.message : 'Unknown parse error');
134
+ console.error('Response preview:', text.substring(0, 200));
135
+ return { widgets: [] };
136
+ }
124
137
  }
125
138
  catch (error) {
126
139
  console.error('Explore request failed:', error);
@@ -173,7 +186,7 @@ export class GoogleTrendsApi {
173
186
  time: `${formatDate(startTime)} ${formatDate(endTime)}`,
174
187
  complexKeywordsRestriction: {
175
188
  keyword: [{
176
- type: 'BROAD',
189
+ type: 'BROAD', //'ENTITY',
177
190
  value: Array.isArray(keyword) ? keyword[0] : keyword
178
191
  }]
179
192
  }
@@ -182,7 +195,7 @@ export class GoogleTrendsApi {
182
195
  locale: hl,
183
196
  requestOptions: {
184
197
  property: '',
185
- backend: 'CM',
198
+ backend: 'CM', //'IZG',
186
199
  category
187
200
  },
188
201
  userConfig: {
@@ -203,5 +216,120 @@ export class GoogleTrendsApi {
203
216
  return { default: { geoMapData: [] } };
204
217
  }
205
218
  }
219
+ async relatedTopics({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
220
+ try {
221
+ // Validate keyword
222
+ if (!keyword || keyword.trim() === '') {
223
+ return { error: new ParseError() };
224
+ }
225
+ const autocompleteResult = await this.autocomplete(keyword, hl);
226
+ if (autocompleteResult.error) {
227
+ return { error: autocompleteResult.error };
228
+ }
229
+ const relatedTopics = autocompleteResult.data?.slice(0, 10).map((suggestion, index) => ({
230
+ topic: {
231
+ mid: `/m/${index}`,
232
+ title: suggestion,
233
+ type: 'Topic'
234
+ },
235
+ value: 100 - index * 10,
236
+ formattedValue: (100 - index * 10).toString(),
237
+ hasData: true,
238
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
239
+ })) || [];
240
+ return {
241
+ data: {
242
+ default: {
243
+ rankedList: [{
244
+ rankedKeyword: relatedTopics
245
+ }]
246
+ }
247
+ }
248
+ };
249
+ }
250
+ catch (error) {
251
+ if (error instanceof Error) {
252
+ return { error: new NetworkError(error.message) };
253
+ }
254
+ return { error: new UnknownError() };
255
+ }
256
+ }
257
+ async relatedQueries({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
258
+ try {
259
+ // Validate keyword
260
+ if (!keyword || keyword.trim() === '') {
261
+ return { error: new ParseError() };
262
+ }
263
+ const autocompleteResult = await this.autocomplete(keyword, hl);
264
+ if (autocompleteResult.error) {
265
+ return { error: autocompleteResult.error };
266
+ }
267
+ const relatedQueries = autocompleteResult.data?.slice(0, 10).map((suggestion, index) => ({
268
+ query: suggestion,
269
+ value: 100 - index * 10,
270
+ formattedValue: (100 - index * 10).toString(),
271
+ hasData: true,
272
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
273
+ })) || [];
274
+ return {
275
+ data: {
276
+ default: {
277
+ rankedList: [{
278
+ rankedKeyword: relatedQueries
279
+ }]
280
+ }
281
+ }
282
+ };
283
+ }
284
+ catch (error) {
285
+ if (error instanceof Error) {
286
+ return { error: new NetworkError(error.message) };
287
+ }
288
+ return { error: new UnknownError() };
289
+ }
290
+ }
291
+ async relatedData({ keyword, geo = 'US', time = 'now 1-d', category = 0, property = '', hl = 'en-US', }) {
292
+ try {
293
+ // Validate keyword
294
+ if (!keyword || keyword.trim() === '') {
295
+ return { error: new ParseError() };
296
+ }
297
+ const autocompleteResult = await this.autocomplete(keyword, hl);
298
+ if (autocompleteResult.error) {
299
+ return { error: autocompleteResult.error };
300
+ }
301
+ const suggestions = autocompleteResult.data?.slice(0, 10) || [];
302
+ const topics = suggestions.map((suggestion, index) => ({
303
+ topic: {
304
+ mid: `/m/${index}`,
305
+ title: suggestion,
306
+ type: 'Topic'
307
+ },
308
+ value: 100 - index * 10,
309
+ formattedValue: (100 - index * 10).toString(),
310
+ hasData: true,
311
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
312
+ }));
313
+ const queries = suggestions.map((suggestion, index) => ({
314
+ query: suggestion,
315
+ value: 100 - index * 10,
316
+ formattedValue: (100 - index * 10).toString(),
317
+ hasData: true,
318
+ link: `/trends/explore?q=${encodeURIComponent(suggestion)}&date=${time}&geo=${geo}`
319
+ }));
320
+ return {
321
+ data: {
322
+ topics,
323
+ queries
324
+ }
325
+ };
326
+ }
327
+ catch (error) {
328
+ if (error instanceof Error) {
329
+ return { error: new NetworkError(error.message) };
330
+ }
331
+ return { error: new UnknownError() };
332
+ }
333
+ }
206
334
  }
207
335
  export default new GoogleTrendsApi();
@@ -3,7 +3,7 @@ export declare const request: (url: string, options: {
3
3
  qs?: Record<string, any>;
4
4
  body?: string | Record<string, any>;
5
5
  headers?: Record<string, string>;
6
- contentType?: 'json' | 'form';
6
+ contentType?: "json" | "form";
7
7
  }) => Promise<{
8
8
  text: () => Promise<string>;
9
9
  }>;
@@ -1,9 +1,19 @@
1
1
  export declare const dailyTrends: ({ geo, lang }: import("./types").DailyTrendingTopicsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
2
2
  export declare const realTimeTrends: ({ geo, trendingHours }: import("./types").RealTimeTrendsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
3
3
  export declare const autocomplete: (keyword: string, hl?: string) => Promise<import("./types").GoogleTrendsResponse<string[]>>;
4
+ export declare const explore: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").ExploreResponse>;
5
+ export declare const interestByRegion: ({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: import("./types").InterestByRegionOptions) => Promise<import("./types").InterestByRegionResponse>;
6
+ export declare const relatedTopics: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedTopicsResponse>>;
7
+ export declare const relatedQueries: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedQueriesResponse>>;
8
+ export declare const relatedData: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedData>>;
4
9
  declare const _default: {
5
10
  dailyTrends: ({ geo, lang }: import("./types").DailyTrendingTopicsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
6
11
  realTimeTrends: ({ geo, trendingHours }: import("./types").RealTimeTrendsOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").DailyTrendingTopics>>;
7
12
  autocomplete: (keyword: string, hl?: string) => Promise<import("./types").GoogleTrendsResponse<string[]>>;
13
+ explore: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").ExploreResponse>;
14
+ interestByRegion: ({ keyword, startTime, endTime, geo, resolution, hl, timezone, category }: import("./types").InterestByRegionOptions) => Promise<import("./types").InterestByRegionResponse>;
15
+ relatedTopics: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedTopicsResponse>>;
16
+ relatedQueries: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedQueriesResponse>>;
17
+ relatedData: ({ keyword, geo, time, category, property, hl, }: import("./types").ExploreOptions) => Promise<import("./types").GoogleTrendsResponse<import("./types").RelatedData>>;
8
18
  };
9
19
  export default _default;
package/dist/esm/index.js CHANGED
@@ -3,9 +3,19 @@ const api = new GoogleTrendsApi();
3
3
  export const dailyTrends = api.dailyTrends.bind(api);
4
4
  export const realTimeTrends = api.realTimeTrends.bind(api);
5
5
  export const autocomplete = api.autocomplete.bind(api);
6
+ export const explore = api.explore.bind(api);
7
+ export const interestByRegion = api.interestByRegion.bind(api);
8
+ export const relatedTopics = api.relatedTopics.bind(api);
9
+ export const relatedQueries = api.relatedQueries.bind(api);
10
+ export const relatedData = api.relatedData.bind(api);
6
11
  // Default export for CommonJS compatibility
7
12
  export default {
8
13
  dailyTrends,
9
14
  realTimeTrends,
10
- autocomplete
15
+ autocomplete,
16
+ explore,
17
+ interestByRegion,
18
+ relatedTopics,
19
+ relatedQueries,
20
+ relatedData
11
21
  };
@@ -2,7 +2,9 @@ export declare enum GoogleTrendsEndpoints {
2
2
  dailyTrends = "dailyTrends",
3
3
  autocomplete = "autocomplete",
4
4
  explore = "explore",
5
- interestByRegion = "interestByRegion"
5
+ interestByRegion = "interestByRegion",
6
+ relatedTopics = "relatedTopics",
7
+ relatedQueries = "relatedQueries"
6
8
  }
7
9
  export declare enum GoogleTrendsTrendingHours {
8
10
  fourHrs = 4,
@@ -4,6 +4,8 @@ export var GoogleTrendsEndpoints;
4
4
  GoogleTrendsEndpoints["autocomplete"] = "autocomplete";
5
5
  GoogleTrendsEndpoints["explore"] = "explore";
6
6
  GoogleTrendsEndpoints["interestByRegion"] = "interestByRegion";
7
+ GoogleTrendsEndpoints["relatedTopics"] = "relatedTopics";
8
+ GoogleTrendsEndpoints["relatedQueries"] = "relatedQueries";
7
9
  })(GoogleTrendsEndpoints || (GoogleTrendsEndpoints = {}));
8
10
  export var GoogleTrendsTrendingHours;
9
11
  (function (GoogleTrendsTrendingHours) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shaivpidadi/trends-js",
3
- "version": "0.0.0-beta.7",
3
+ "version": "0.0.0-beta.8",
4
4
  "description": "Google Trends API for Node.js",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -40,4 +40,4 @@
40
40
  "ts-jest": "^29.1.0",
41
41
  "typescript": "^5.0.0"
42
42
  }
43
- }
43
+ }