├── .babelrc ├── .codeclimate.yml ├── .eslintrc ├── .gitignore ├── .npmignore ├── .travis.yml ├── CHANGES.md ├── LICENSE ├── README.md ├── allCategories.txt ├── examples.js ├── package-lock.json ├── package.json ├── src ├── api.js ├── index.js ├── request.js └── utilities.js ├── test ├── api.spec.js ├── index.spec.js └── utilities.spec.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": ["babel-plugin-add-module-exports", "transform-es2015-destructuring", "transform-object-rest-spread" ] 4 | } -------------------------------------------------------------------------------- /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engines: 3 | # ... CONFIG CONTENT ... 4 | eslint: 5 | enabled: true 6 | config: 7 | languages: 8 | - javascript 9 | fixme: 10 | enabled: true 11 | ratings: 12 | paths: 13 | - "**.js" 14 | - "**.jsx" 15 | exclude_paths: ["lib", "webpack.config.js", "examples.js"] 16 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "globalReturn": true, 4 | "jsx": true, 5 | "modules": true 6 | }, 7 | 8 | "env": { 9 | "browser": true, 10 | "es6": true, 11 | "node": true 12 | }, 13 | 14 | "globals": { 15 | "document": false, 16 | "escape": false, 17 | "navigator": false, 18 | "unescape": false, 19 | "window": false, 20 | "describe": true, 21 | "before": true, 22 | "it": true, 23 | "expect": true, 24 | "sinon": true 25 | }, 26 | 27 | "parser": "babel-eslint", 28 | 29 | "plugins": [ 30 | 31 | ], 32 | 33 | "rules": { 34 | "block-scoped-var": 2, 35 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 36 | "camelcase": [2, { "properties": "always" }], 37 | "comma-dangle": [2, "always-multiline"], 38 | "comma-spacing": [2, { "before": false, "after": true }], 39 | "comma-style": [2, "last"], 40 | "complexity": 0, 41 | "consistent-return": 2, 42 | "consistent-this": 0, 43 | "curly": [2, "multi-line"], 44 | "default-case": 0, 45 | "dot-location": [2, "property"], 46 | "dot-notation": 0, 47 | "eol-last": 2, 48 | "eqeqeq": [2, "allow-null"], 49 | "func-names": 0, 50 | "func-style": 0, 51 | "generator-star-spacing": [2, "both"], 52 | "guard-for-in": 0, 53 | "handle-callback-err": [2, "^(err|error|anySpecificError)$" ], 54 | "indent": [2, 2, { "SwitchCase": 1 }], 55 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 56 | "linebreak-style": 0, 57 | "max-depth": 0, 58 | "max-len": [2, 80, 4], 59 | "max-nested-callbacks": 0, 60 | "max-params": 0, 61 | "max-statements": 0, 62 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 63 | "newline-after-var": [2, "always"], 64 | "new-parens": 2, 65 | "no-alert": 0, 66 | "no-array-constructor": 2, 67 | "no-bitwise": 0, 68 | "no-caller": 2, 69 | "no-catch-shadow": 0, 70 | "no-cond-assign": 2, 71 | "no-console": 0, 72 | "no-constant-condition": 0, 73 | "no-continue": 0, 74 | "no-control-regex": 2, 75 | "no-debugger": 2, 76 | "no-delete-var": 2, 77 | "no-div-regex": 0, 78 | "no-dupe-args": 2, 79 | "no-dupe-keys": 2, 80 | "no-duplicate-case": 2, 81 | "no-else-return": 2, 82 | "no-empty": 0, 83 | "no-empty-character-class": 2, 84 | "no-empty-label": 2, 85 | "no-eq-null": 0, 86 | "no-eval": 2, 87 | "no-ex-assign": 2, 88 | "no-extend-native": 2, 89 | "no-extra-bind": 2, 90 | "no-extra-boolean-cast": 2, 91 | "no-extra-parens": 0, 92 | "no-extra-semi": 0, 93 | "no-extra-strict": 0, 94 | "no-fallthrough": 2, 95 | "no-floating-decimal": 2, 96 | "no-func-assign": 2, 97 | "no-implied-eval": 2, 98 | "no-inline-comments": 0, 99 | "no-inner-declarations": [2, "functions"], 100 | "no-invalid-regexp": 2, 101 | "no-irregular-whitespace": 2, 102 | "no-iterator": 2, 103 | "no-label-var": 2, 104 | "no-labels": 2, 105 | "no-lone-blocks": 0, 106 | "no-lonely-if": 0, 107 | "no-loop-func": 0, 108 | "no-mixed-requires": 0, 109 | "no-mixed-spaces-and-tabs": [2, false], 110 | "no-multi-spaces": 2, 111 | "no-multi-str": 2, 112 | "no-multiple-empty-lines": [2, { "max": 1 }], 113 | "no-native-reassign": 2, 114 | "no-negated-in-lhs": 2, 115 | "no-nested-ternary": 0, 116 | "no-new": 2, 117 | "no-new-func": 2, 118 | "no-new-object": 2, 119 | "no-new-require": 2, 120 | "no-new-wrappers": 2, 121 | "no-obj-calls": 2, 122 | "no-octal": 2, 123 | "no-octal-escape": 2, 124 | "no-path-concat": 0, 125 | "no-plusplus": 0, 126 | "no-process-env": 0, 127 | "no-process-exit": 0, 128 | "no-proto": 2, 129 | "no-redeclare": 2, 130 | "no-regex-spaces": 2, 131 | "no-reserved-keys": 0, 132 | "no-restricted-modules": 0, 133 | "no-return-assign": 2, 134 | "no-script-url": 0, 135 | "no-self-compare": 2, 136 | "no-sequences": 2, 137 | "no-shadow": 0, 138 | "no-shadow-restricted-names": 2, 139 | "no-spaced-func": 2, 140 | "no-sparse-arrays": 2, 141 | "no-sync": 0, 142 | "no-ternary": 0, 143 | "no-throw-literal": 2, 144 | "no-trailing-spaces": 2, 145 | "no-undef": 2, 146 | "no-undef-init": 2, 147 | "no-undefined": 0, 148 | "no-underscore-dangle": 0, 149 | "no-unneeded-ternary": 2, 150 | "no-unreachable": 2, 151 | "no-unused-expressions": 0, 152 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 153 | "no-use-before-define": 2, 154 | "no-var": 0, 155 | "no-void": 0, 156 | "no-warning-comments": 0, 157 | "no-with": 2, 158 | "one-var": 0, 159 | "operator-assignment": 0, 160 | "operator-linebreak": [2, "after"], 161 | "padded-blocks": 0, 162 | "quote-props": 0, 163 | "quotes": [2, "single", "avoid-escape"], 164 | "radix": 2, 165 | "semi": [2, "always"], 166 | "semi-spacing": 0, 167 | "sort-vars": 0, 168 | "space-after-keywords": [2, "always"], 169 | "space-before-blocks": [2, "always"], 170 | "space-before-function-paren": [2, {"anonymous": "never", "named": "never"}], 171 | "space-in-brackets": 0, 172 | "space-in-parens": [2, "never"], 173 | "space-infix-ops": 2, 174 | "space-return-throw-case": 2, 175 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 176 | "spaced-comment": [2, "always"], 177 | "strict": 0, 178 | "use-isnan": 2, 179 | "valid-jsdoc": 0, 180 | "valid-typeof": 2, 181 | "wrap-iife": [2, "any"], 182 | "wrap-regex": 0, 183 | "yoda": [2, "never"] 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | testFile.js 31 | 32 | # ignore built files 33 | lib 34 | 35 | # ignore mac files 36 | .DS_Store 37 | 38 | # ignore webstorm files 39 | .idea -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | .nyc_output 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # node-waf configuration 21 | .lock-wscript 22 | 23 | # Compiled binary addons (http://nodejs.org/api/addons.html) 24 | build/Release 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | testFile.js 31 | allCategories.txt 32 | 33 | test 34 | src 35 | webpack.config.js 36 | .travis.yml 37 | .codeclimate.yml 38 | .eslintrc 39 | .babelrc 40 | 41 | # ignore mac files 42 | .DS_Store -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | after_success: 5 | - npm run coveralls 6 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | #### [v4.9.0] 2 | > Feb 2, 2019 3 | - Adds support for a single keyword string with an array of geo locations 4 | [#116]: https://github.com/pat310/google-trends-api/pull/116 5 | 6 | #### [v4.7.0] 7 | > July 14, 2018 8 | - Allowing locations for different keywords 9 | [#111]: https://github.com/pat310/google-trends-api/pull/111 10 | 11 | #### [v4.6.2] 12 | > May 29, 2018 13 | - Fixing 429 errors from google trends 14 | [#106]: https://github.com/pat310/google-trends-api/pull/106 15 | 16 | #### [v4.6.1] 17 | > Feb 21, 2018 18 | - Fixing proxy bug by adding proxy to `nextOptions` 19 | [#95]: https://github.com/pat310/google-trends-api/pull/94 20 | 21 | ## [v4.6.0] 22 | > Feb 19, 2018 23 | - Ability to specify a google property filter 24 | [#94]: https://github.com/pat310/google-trends-api/pull/94 25 | 26 | # [v4.5.0] 27 | > Jan 31, 2018 28 | - Adding ability to use a proxy server 29 | [#92]: https://github.com/pat310/google-trends-api/pull/92 30 | 31 | ## [v4.4.0] 32 | > Jan 12, 2018 33 | - Added `timezone` number, defaults to the time zone difference in minutes from UTC to host system settings 34 | 35 | [#90]: https://github.com/pat310/google-trends-api/pull/90 36 | 37 | ## [v4.3.0] 38 | > Oct 22, 2017 39 | - Added `granularTimeResolution` boolean as optional input object parameter, when true will default to finest time resolution possible 40 | 41 | [#84]: https://github.com/pat310/google-trends-api/pull/84 42 | 43 | ## [v4.2.2] 44 | > Sep 7, 2017 45 | - Using widget `id` rather than `title` for determining token. Title changes for region from `Interest by region` to `Interest by subregion` in certain scenarios. When this would happen, the lookup would break. 46 | 47 | [#78]: https://github.com/pat310/google-trends-api/pull/78 48 | 49 | ## [v4.2.1] 50 | > Sep 1, 2017 51 | - Unicode characters in results are decoded by default 52 | - Corrected a bug when a user tries to perform a comparison with a search topic and a search term 53 | 54 | [#74]: https://github.com/pat310/google-trends-api/pull/74 55 | [#76]: https://github.com/pat310/google-trends-api/pull/76 56 | 57 | ## [v4.2.0] 58 | > Aug 21, 2017 59 | - Added a new api method which returns the results from the "add a search term" input box in the UI: `autoComplete` 60 | - Added a new optional parameter to include in the search query: `category`. Category is input as a [number](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) 61 | 62 | [#70]: https://github.com/pat310/google-trends-api/pull/70 63 | [#72]: https://github.com/pat310/google-trends-api/pull/72 64 | 65 | ## [v4.1.0] 66 | > Mar 16, 2017 67 | - Added ability to search trends across [multiple keywords](https://github.com/pat310/google-trends-api#multiple-keywords) 68 | - Catching errors on failed JSON.parse 69 | 70 | [#54]: https://github.com/pat310/google-trends-api/pull/54 71 | [#58]: https://github.com/pat310/google-trends-api/pull/58 72 | 73 | ## [v4.0.1] 74 | > Feb 13, 2017 75 | - actually building before committing 76 | - added a preversion script to ensure build occurs 77 | 78 | ## [v4.0.0] 79 | > Feb 13, 2017 80 | 81 | - removed all old api methods 82 | - added four new api methods: 83 | - `interestByRegion` 84 | - `interestOverTime` 85 | - `relatedQueries` 86 | - `relatedTopics` 87 | - removed all dependencies 88 | - adding [codeclimate](https://codeclimate.com/github/pat310/google-trends-api) 89 | - fixing [coveralls](https://coveralls.io/github/pat310/google-trends-api) 90 | - removed old tests and added new tests for new methods 91 | - adding eslint and following [airbnb](https://github.com/airbnb/javascript) style guide 92 | - updated README accordingly 93 | 94 | [#47]: https://github.com/pat310/google-trends-api/pull/47 95 | 96 | ## [v3.0.2] 97 | > Feb 3, 2017 98 | 99 | - removing node specific `__dirname` so library can be used in browser 100 | 101 | [#44]: https://github.com/pat310/google-trends-api/pull/44 102 | 103 | ## [v3.0.1] 104 | > Oct 31, 2016 105 | 106 | - removing `cheerio` as a dependency by replacing it with regex ([#35]) 107 | 108 | [#35]: https://github.com/pat310/google-trends-api/pull/35 109 | 110 | ## [v3.0.0] 111 | > Oct 22, 2016 112 | 113 | - `topRelated` now correctly using `TOP_QUERIES` rather than `RISING_QUERIES` ([#34]) 114 | - `topRelated` now accepts an optional `timePeriod` object that will return trend data based on a provided time period ([#34]) 115 | - Added `risingSearches` method which accepts `category`, `timePeriod` and `geo` ([#34]) 116 | 117 | [#34]: https://github.com/pat310/google-trends-api/pull/34 118 | 119 | ## [v2.1.0] 120 | > Oct 22, 2016 121 | 122 | - `trendData` now accepts an optional `timePeriod` object that will return trend data based on a provided time period ([#33]) 123 | 124 | [#33]: https://github.com/pat310/google-trends-api/pull/33 125 | 126 | ## [v2.0.0] 127 | > Oct 22, 2016 128 | 129 | - `trendData` now returns [IETF-compliant RFC 2822 timestamps](https://tools.ietf.org/html/rfc2822#page-14) ([#32]) 130 | - Adding New Zealand to list of country codes 131 | 132 | [#32]: https://github.com/pat310/google-trends-api/pull/32 133 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Patrick Trasborg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # google-trends-api 2 | 3 | [![NPM](https://nodei.co/npm/google-trends-api.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/google-trends-api/) 4 | 5 | [![npm version](https://badge.fury.io/js/google-trends-api.svg)](https://badge.fury.io/js/google-trends-api) 6 | [![Build status](https://img.shields.io/travis/pat310/google-trends-api.svg?style=flat-square)](https://travis-ci.org/pat310/google-trends-api/) 7 | [![Coverage Status](https://coveralls.io/repos/github/pat310/google-trends-api/badge.svg?branch=master)](https://coveralls.io/github/pat310/google-trends-api?branch=master) 8 | [![Code Climate](https://codeclimate.com/github/pat310/google-trends-api/badges/gpa.svg)](https://codeclimate.com/github/pat310/google-trends-api) 9 | [![Dependency Status](https://img.shields.io/david/pat310/google-trends-api.svg?style=flat-square)](https://david-dm.org/pat310/google-trends-api) 10 | [![Known Vulnerabilities](https://snyk.io/test/github/pat310/google-trends-api/badge.svg)](https://snyk.io/test/github/pat310/google-trends-api) 11 | 12 | ## v3 to v4 13 | [Big changes](/CHANGES.md)! The old google-trends endpoints are deprecated and are heavily throttled so this library has changed significantly. You can choose to download the old version via `npm install google-trends-api@3.0.2` but it is discouraged. 14 | 15 | ## Introduction 16 | This library provides an API layer to [google trends](https://www.google.com/trends/) data. Due to CORS restrictions, this library is intended to be used in node. It is constantly being expanded and improved so please check back frequently. Also, please feel free to contribute to make the library even better! :dog: 17 | 18 | ### Syntax 19 | ```js 20 | const googleTrends = require('google-trends-api'); 21 | 22 | googleTrends.apiMethod(optionsObject, [callback]) 23 | ``` 24 | 25 | #### Parameters 26 | **optionsObject** 27 | An object with the following options keys: 28 | * **keyword** Target search term(s) `string` or `array` if you wish to compare search terms **required** 29 | * **startTime** Start of time period of interest (`new Date()` object). If `startTime` is not provided, a date of January 1, 2004 is assumed (this is the oldest available google trends data) 30 | * **endTime** End of time period of interest (`new Date()` object). If `endTime` is not provided, the current date is selected. 31 | * **geo** Location of interest (`string` or `array` if you wish to provide separate locations for each keyword). 32 | * **hl** Preferred language (`string` [defaults to english](https://sites.google.com/site/tomihasa/google-language-codes)) 33 | * **timezone** Timezone (`number` defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 34 | * **category** Category to search within (`number` defaults to [all categories](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories)) 35 | * **property** Google property to filter on. Defaults to web search. (enumerated `string` ['images', 'news', 'youtube' or 'froogle'] where froogle is Google Shopping results) 36 | * **resolution** Granularity of the geo search (enumerated `string` ['COUNTRY', 'REGION', 'CITY', 'DMA']). `resolution` is specific to the [interestByRegion](#interestByRegion) method. 37 | * **granularTimeResolution** Boolean that dictates if the results should be given in a finer time resolution (if `startTime` and `endTime` is less than one day, this should be set to `true`) 38 | 39 | **callback** 40 | Optional callback function where the first parameter is an error and the second parameter is the result. If no callback is provided, then a promise is returned. 41 | 42 | ## Table of contents 43 | * [Installation](#installation) 44 | * [API](#api) 45 | * [Promises](#promises) 46 | * [Callbacks](#callbacks) 47 | * [Proxy Server](#proxy-server) 48 | * [Examples](#examples) 49 | * [API Methods](#api-methods) 50 | * [autoComplete](#autocomplete) 51 | * [dailyTrends](#dailyTrends) 52 | * [interestOverTime](#interestovertime) 53 | * [interestByRegion](#interestbyregion) 54 | * [realTimeTrends](#realTimeTrends) 55 | * [relatedQueries](#relatedqueries) 56 | * [relatedTopics](#relatedtopics) 57 | * [Geo help](#geo-help) 58 | * [List of categories](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) 59 | * [Big Thanks](#big-thanks) 60 | 61 |
62 | 63 | ## Installation 64 | To install this package, clone this git repository and include it in your project's node_modules or simply: 65 | 66 | ``` 67 | npm install google-trends-api 68 | ``` 69 | 70 | Require google-trends-api in your script and give it a variable name: 71 | 72 | ```js 73 | const googleTrends = require('google-trends-api'); 74 | ``` 75 | 76 | You will now be able to access methods on `googleTrends`. See the [API Methods section](#api-methods) below to see the methods available and their syntax. 77 | 78 | [back to top](#introduction) 79 | 80 |
81 | 82 | ## API 83 | 84 | ### Promises 85 | By default, all the API's return a promise for the results. Example: 86 | ```js 87 | googleTrends.interestOverTime({keyword: 'Women\'s march'}) 88 | .then(function(results){ 89 | console.log('These results are awesome', results); 90 | }) 91 | .catch(function(err){ 92 | console.error('Oh no there was an error', err); 93 | }); 94 | ``` 95 | 96 | ### Callbacks 97 | All API methods can alternatively take a callback function as the second parameter. For example: 98 | ```js 99 | googleTrends.interestOverTime({keyword: 'Women\'s march'}, function(err, results){ 100 | if(err) console.error('there was an error!', err); 101 | else console.log('my sweet sweet results', results); 102 | }) 103 | ``` 104 | 105 | ### Proxy Server 106 | A proxy server can be used by specifying an http agent as part of the query. This example uses [https-proxy-agent](https://www.npmjs.com/package/https-proxy-agent) 107 | 108 | ```js 109 | const HttpsProxyAgent = require('https-proxy-agent'); 110 | 111 | let proxyAgent = new HttpsProxyAgent('http://proxy-host:8888/'); 112 | 113 | let query = { 114 | keyword: 'Women\'s march', 115 | agent: proxyAgent 116 | }; 117 | 118 | googleTrends.interestOverTime(query) 119 | .then(function(results){ 120 | console.log('These proxied results are incredible', results); 121 | }) 122 | .catch(function(err){ 123 | console.error('Oh no there was an error, double check your proxy settings', err); 124 | }); 125 | ``` 126 | 127 | ### Multiple Keywords 128 | Compare multiple keywords with any of the api methods by supplying an `array` instead of a single `string` 129 | ```js 130 | googleTrends.interestOverTime({keyword: ['Women\'s march', 'Trump Inauguration']}) 131 | .then(function(results){ 132 | console.log('These results are awesome', results); 133 | }) 134 | .catch(function(err){ 135 | console.error('Oh no there was an error', err); 136 | }); 137 | ``` 138 | 139 | 140 | ### Examples 141 | There are examples available for each API method in the root directory of the module. **Note:** Each example in [examples.js](/examples.js) needs to be uncommented. 142 | 143 | ### API Methods 144 | The following API methods are available: 145 | * [autoComplete](#autocomplete): Returns the results from the "Add a search term" input box in the google trends UI. These results (Topics) can then be used in the other API methods. **Note**: Search terms and Topics are measured differently, so `relatedTopics` will not work with comparisons that contain both Search terms and Topics. 146 | 147 | * [dailyTrends](#dailyTrends): Daily Search Trends highlights searches that jumped significantly in traffic among all searches over the past 24 hours and updates hourly. These search trends show the specific queries that were searched, and the absolute number of searches made. 20 daily trending search results are returned.You can search retroactively for up to 15 days in the past. 148 | 149 | * [interestOverTime](#interestovertime): Numbers represent search interest relative to the highest point on the chart for the given region and time. A value of 100 is the peak popularity for the term. A value of 50 means that the term is half as popular. Likewise a score of 0 means the term was less than 1% as popular as the peak. If you use multiple keywords for a comparison, the return data will also contain an average result for each keyword. 150 | 151 | * [interestByRegion](#interestbyregion): See in which location your term was most popular during the specified time frame. Values are calculated on a scale from 0 to 100, where 100 is the location with the most popularity as a fraction of total searches in that location, a value of 50 indicates a location which is half as popular, and a value of 0 indicates a location where the term was less than 1% as popular as the peak.

**Note:** A higher value means a higher proportion of all queries, not a higher absolute query count. So a tiny country where 80% of the queries are for "bananas" will get twice the score of a giant country where only 40% of the queries are for "bananas". 152 | 153 | * [realTimeTrends](#realTimeTrends): Realtime Search Trends highlight stories that are trending across Google surfaces within the last 24 hours, and are updated in realtime. These stories are a collection of Knowledge Graph topics, Search interest, trending YouTube videos, and/or Google News articles detected by Google's algorithms. 13 real time trending stories are returned. 154 | 155 | * [relatedQueries](#relatedqueries): Users searching for your term also searched for these queries. The following metrics are returned: 156 | * **Top** - The most popular search queries. Scoring is on a relative scale where a value of 100 is the most commonly searched query, 50 is a query searched half as often, and a value of 0 is a query searched for less than 1% as often as the most popular query. 157 | * **Rising** - Queries with the biggest increase in search frequency since the last time period. Results marked "Breakout" had a tremendous increase, probably because these queries are new and had few (if any) prior searches. 158 | 159 | * [relatedTopics](#relatedtopics): Users searching for your term also searched for these topics. The following metrics are returned: 160 | * **Top** - The most popular topics. Scoring is on a relative scale where a value of 100 is the most commonly searched topic, a value of 50 is a topic searched half as often, and a value of 0 is a topic searched for less than 1% as often as the most popular topic. 161 | * **Rising** - Related topics with the biggest increase in search frequency since the last time period. Results marked "Breakout" had a tremendous increase, probably because these topics are new and had few (if any) prior searches. 162 | 163 | [back to top](#introduction) 164 | 165 |


166 | 167 | #### autoComplete 168 | * Results from the "add a search term" input box in the google trends UI* 169 | 170 | #### Syntax 171 | `googleTrends.autoComplete({keyword: string}, cbFunc)` 172 | 173 | Requires an `object` as the first parameter with the following keys: 174 | * `keyword` - **required** - type `string` - the search term of interest 175 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 176 | 177 | Optional callback `function` as the second parameter (otherwise returns a promise) 178 | 179 | ##### Example 180 | Returning the auto-complete results for 'Back to School' 181 | 182 | ###### Input 183 | ```js 184 | googleTrends.autoComplete({keyword: 'Back to School'}) 185 | .then(function(results) { 186 | console.log(results); 187 | }) 188 | .catch(function(err) { 189 | console.error(err); 190 | }) 191 | ``` 192 | 193 | ###### Output 194 | ```js 195 | {"default":{"topics":[{"mid":"/m/0414j6","title":"Back to School","type":"1986 film"},{"mid":"/m/068pw8","title":"Back to school","type":"Topic"},{"mid":"/m/04vwgn","title":"Fight Back to School","type":"1991 film"},{"mid":"/m/05357_","title":"Tax holiday","type":"Holiday"},{"mid":"/m/02pb6kt","title":"Fight Back to School II","type":"1992 film"}]}} 196 | ``` 197 | **Note:** You can then use these results in the other API methods. For example, if you wanted `interestOverTime` for 'Back to School' where the type is 'Topic', you would then use: 198 | `googleTrends.interestOverTime({keyword: '/m/068pw8'})` 199 | 200 | [back to top](#introduction) 201 | 202 |
203 | 204 | #### dailyTrends 205 | *Daily Search Trends highlights searches that jumped significantly in traffic among all searches over the past 24 hours and updates hourly. These search trends show the specific queries that were searched, and the absolute number of searches made. 20 daily trending search results are returned* 206 | 207 | ##### Syntax 208 | `googleTrends.dailyTrends({ geo: string }, cbFunc)` 209 | 210 | Requires an `object` as the first parameter with the following keys: 211 | 212 | * `geo` - **required** - type `string` - geocode for a country. For example, `geo: 'US'` will target United States or `geo: 'FR'` will target France. 213 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english). 214 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 215 | * `trendDate` - *optional* - type `Date` object - the date you are interesting in retrieving trends information for (defaults to the current date). **Note that querying for a date more than 15 days in the past will result in an error.** 216 | 217 | Optional callback `function` as the second parameter (otherwise returns a promise) 218 | 219 | ##### Example 220 | Returning real time trending stories for the United States region. 221 | 222 | ###### Input 223 | ```js 224 | googleTrends.dailyTrends({ 225 | trendDate: new Date('2019-01-10'), 226 | geo: 'US', 227 | }, function(err, results) { 228 | if (err) { 229 | console.log(err); 230 | }else{ 231 | console.log(results); 232 | } 233 | }); 234 | ``` 235 | 236 | ###### Output 237 | ```js 238 | { 239 | default : [Object]{ 240 | trendingSearchesDays : [Array] 241 | [0] : [Object]{ 242 | date : String 243 | formattedDate: String 244 | trendingSearches : [Array]{ 245 | [0] : [Object] //First trending result 246 | } 247 | [1] : [Object]{ 248 | date : String 249 | formattedDate: String 250 | trendingSearches : [Array]{ 251 | [0] : [Object] //first trending result 252 | ... 253 | [19] : [Object] //20th trending result 254 | } 255 | } 256 | } 257 | endDateForNextRequest : String, 258 | rssFeedPageUrl : String, 259 | } 260 | } 261 | ``` 262 | 263 | [back to top](#introduction) 264 | 265 |
266 | 267 | #### interestOverTime 268 | *Search interest relative to the highest point on the chart for the given region and time (100 is the peak popularity for the term)* 269 | 270 | ##### Syntax 271 | `googleTrends.interestOverTime({keyword: string, startTime: Date, endTime: Date, geo: string}, cbFunc)` 272 | 273 | Requires an `object` as the first parameter with the following keys: 274 | * `keyword` - **required** - type `string` or `array` - the search term(s) of interest 275 | * `startTime` - *optional* - type `Date` object - the start of the time range of interest (defaults to `new Date('2004-01-01')` if not supplied) 276 | * `endTime` - *optional* - type `Date` object - the end of the time range of interest (defaults to `new Date(Date.now())` if not supplied) 277 | * `geo` - *optional* - type `string` or `array` - geocode(s) for a country, region, or DMA depending on the granularity required (defaults to worldwide). For example, `geo: 'US-CA-800'` will target the Bakersfield, California, United States or `geo: 'US'` will just target the US. Passing `geo: ['US-CA, US-VA'], keyword: ['wine', 'peanuts']` will search for wine in California and peanuts in Virginia. 278 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 279 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 280 | * `category` - *optional* - type `number` - a number corresponding to a particular category to query within (defaults to all categories), see the [category wiki](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) for a complete list 281 | * `granularTimeResolution` - *optional* - type `boolean` - if `true`, will try to return results to a finer time resolution (only relevant for `startTime` and `endTime` less than one week) 282 | 283 | Optional callback `function` as the second parameter (otherwise returns a promise) 284 | 285 | The resolution of the search changes automatically depending on the search duration. The wider the duration window, the worse the resolution (for example, a search duration with a `startTime` and `endTime` that ends years apart will return a resolution in months, while a search duration with a `startTime` and `endTime` a few hours apart will return a resolution in minutes). 286 | 287 | ##### Example 1 288 | Returning the search interest over time for 'Valentines Day' (by default from 2004-01-01 to today) 289 | 290 | ###### Input 291 | ```js 292 | googleTrends.interestOverTime({keyword: 'Valentines Day'}) 293 | .then(function(results){ 294 | console.log(results); 295 | }) 296 | .catch(function(err){ 297 | console.error(err); 298 | }); 299 | ``` 300 | 301 | ###### Output 302 | ```js 303 | {"default":{"timelineData":[{"time":"1072915200","formattedTime":"Jan 2004","formattedAxisTime":"Jan 1, 2004","value":[26],"formattedValue":["26"]},{"time":"1075593600","formattedTime":"Feb 2004","formattedAxisTime":"Feb 1, 2004","value":[74],"formattedValue":["74"]}, 304 | ... 305 | {"time":"1483228800","formattedTime":"Jan 2017","formattedAxisTime":"Jan 1, 2017","value":[18],"formattedValue":["18"]},{"time":"1485907200","formattedTime":"Feb 2017","formattedAxisTime":"Feb 1, 2017","value":[72],"formattedValue":["72"]}],"averages":[]}} 306 | ``` 307 | 308 | ##### Example 2 309 | Returning the search interest over time for 'Valentines Day' from the past four hours. Note that the resolution is by minute since our query duration is shorter. 310 | 311 | ###### Input 312 | ```js 313 | googleTrends.interestOverTime({keyword: 'Valentines Day', startTime: new Date(Date.now() - (4 * 60 * 60 * 1000))}, function(err, results) { 314 | if (err) console.log('oh no error!', err); 315 | else console.log(results); 316 | }); 317 | ``` 318 | 319 | ###### Output 320 | ```js 321 | {"default":{"timelineData":[{"time":"1487026800","formattedTime":"Feb 13, 2017 at 6:00 PM","formattedAxisTime":"6:00 PM","value":[49],"formattedValue":["49"]},{"time":"1487026860","formattedTime":"Feb 13, 2017 at 6:01 PM","formattedAxisTime":"6:01 PM","value":[50],"formattedValue":["50"]}, 322 | ... 323 | {"time":"1487040180","formattedTime":"Feb 13, 2017 at 9:43 PM","formattedAxisTime":"9:43 PM","value":[88],"formattedValue":["88"]},{"time":"1487040240","formattedTime":"Feb 13, 2017 at 9:44 PM","formattedAxisTime":"9:44 PM","value":[81],"formattedValue":["81"]}],"averages":[]}} 324 | ``` 325 | 326 | [back to top](#introduction) 327 | 328 |
329 | 330 | #### interestByRegion 331 | *See in which location your term was most popular during the specified time frame. Values are calculated on a scale from 0 to 100, where 100 is the location with the most popularity as a fraction of total searches in that location.* 332 | 333 | ##### Syntax 334 | `googleTrends.interestByRegion({keyword: string, startTime: Date, endTime: Date, geo: string, resolution: string}, cbFunc)` 335 | 336 | Requires an `object` as the first parameter with the following keys: 337 | * `keyword` - **required** - type `string` or `array` - the search term(s) of interest 338 | * `startTime` - *optional* - type `Date` object - the start of the time range of interest (defaults to `new Date('2004-01-01')` if not supplied) 339 | * `endTime` - *optional* - type `Date` object - the end of the time range of interest (defaults to `new Date(Date.now())` if not supplied) 340 | * `geo` - *optional* - type `string` or `array` - geocode(s) for a country, region, or DMA depending on the granularity required (defaults to worldwide). For example, `geo: 'US-CA-800'` will target the Bakersfield, California, United States or `geo: 'US'` will just target the US. Passing `geo: ['US-CA, US-VA'], keyword: ['wine', 'peanuts']` will search for wine in California and peanuts in Virginia. 341 | * `resolution` - *optional* - type `enumerated string` either `COUNTRY`, `REGION`, `CITY` or `DMA`. Resolution is selected by default otherwise. Trying to select a resolution larger than a specified `geo` will return an error. 342 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 343 | for results (defaults to english) 344 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 345 | * `category` - *optional* - type `number` - a number corresponding to a particular category to query within (defaults to all categories), see the [category wiki](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) for a complete list 346 | 347 | Optional callback `function` as the second parameter (otherwise returns a promise) 348 | 349 | ##### Example 1 350 | Returning the search interest by cities around the world for 'Donald Trump' from February 01, 2017 to February 06, 2017. 351 | 352 | ###### Input 353 | ```js 354 | googleTrends.interestByRegion({keyword: 'Donald Trump', startTime: new Date('2017-02-01'), endTime: new Date('2017-02-06'), resolution: 'CITY'}) 355 | .then((res) => { 356 | console.log(res); 357 | }) 358 | .catch((err) => { 359 | console.log(err); 360 | }) 361 | ``` 362 | 363 | ###### Output 364 | ```js 365 | {"default":{"geoMapData":[{"coordinates":{"lat":18.594395,"lng":-72.3074326},"geoName":"Port-au-Prince","value":[100],"formattedValue":["100"],"maxValueIndex":0},{"coordinates":{"lat":43.467517,"lng":-79.6876659},"geoName":"Oakville","value":[90],"formattedValue":["90"],"maxValueIndex":0}, 366 | ... 367 | {"coordinates":{"lat":40.9312099,"lng":-73.8987469},"geoName":"Yonkers","value":[69],"formattedValue":["69"],"maxValueIndex":0}]}} 368 | ``` 369 | 370 | ##### Example 2 371 | Returning the search interest by cities in California for 'Donald Trump' from February 01, 2017 to February 06, 2017. 372 | 373 | ###### Input 374 | ```js 375 | googleTrends.interestByRegion({keyword: 'Donald Trump', startTime: new Date('2017-02-01'), endTime: new Date('2017-02-06'), geo: 'US-CA'}) 376 | .then((res) => { 377 | console.log(res); 378 | }) 379 | .catch((err) => { 380 | console.log(err); 381 | }) 382 | ``` 383 | 384 | ###### Output 385 | ```js 386 | {"default":{"geoMapData":[{"geoCode":"807","geoName":"San Francisco-Oakland-San Jose CA","value":[100],"formattedValue":["100"],"maxValueIndex":0},{"geoCode":"828","geoName":"Monterey-Salinas CA","value":[100],"formattedValue":["100"],"maxValueIndex":0}, 387 | ... 388 | {"geoCode":"811","geoName":"Reno NV","value":[12],"formattedValue":["12"],"maxValueIndex":0},{"geoCode":"813","geoName":"Medford-Klamath Falls OR","value":[4],"formattedValue":["4"],"maxValueIndex":0}]}} 389 | ``` 390 | 391 | [back to top](#introduction) 392 | 393 |
394 | 395 | #### realtimeTrends 396 | *Realtime Search Trends highlight stories that are trending across Google surfaces within the last 24 hours, and are updated in realtime. 13 real time trending stories are returned* 397 | 398 | ##### Syntax 399 | `googleTrends.realTimeTrends({ geo: string }, cbFunc)` 400 | 401 | Requires an `object` as the first parameter with the following keys: 402 | 403 | * `geo` - **required** - type `string` - geocode for a country. For example, `geo: 'US'` will target United States or `geo: 'FR'` will target France. 404 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 405 | for results (defaults to english) 406 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 407 | * `category` - *optional* - type `string` - a string corresponding to a particular category to query within (defaults to all categories): 408 | All : 'all' 409 | Entertainment: 'e' 410 | Business : 'b' 411 | Science/Tech : 't' 412 | Health : 'm' 413 | Sports : 's' 414 | Top Stories : 'h' 415 | 416 | Optional callback `function` as the second parameter (otherwise returns a promise) 417 | 418 | ##### Example 419 | Returning real time trending stories for the United States region. 420 | 421 | ###### Input 422 | ```js 423 | googleTrends.realTimeTrends({ 424 | geo: 'US', 425 | category: 'all', 426 | }, function(err, results) { 427 | if (err) { 428 | console.log(err); 429 | } else { 430 | console.log(results); 431 | } 432 | }); 433 | ``` 434 | 435 | ###### Output 436 | ```js 437 | { 438 | featuredStoryIds : [Array], // Empty 439 | trendingStoryIds : [Array], // 300 trending story IDs 440 | storySummaries : [Object] 441 | { 442 | featuredStories : [Array], // Empty 443 | trendingStories : [Array], // 13 top trending stories 444 | }, 445 | date : "Date-String", 446 | hideAllImages : Boolean, 447 | } 448 | ``` 449 | 450 | [back to top](#introduction) 451 | 452 |
453 | 454 | #### relatedQueries 455 | *Users searching for your term also searched for these queries.* 456 | 457 | ##### Syntax 458 | `googleTrends.relatedQueries({keyword: string, startTime: Date, endTime: Date, geo: string}, cbFunc)` 459 | 460 | Requires an `object` as the first parameter with the following keys: 461 | * `keyword` - **required** - type `string` or `array` - the search term(s) of interest 462 | * `startTime` - *optional* - type `Date` object - the start of the time range of interest (defaults to `new Date('2004-01-01')` if not supplied) 463 | * `endTime` - *optional* - type `Date` object - the end of the time range of interest (defaults to `new Date(Date.now())` if not supplied) 464 | * `geo` - *optional* - type `string` or `array` - geocode(s) for a country, region, or DMA depending on the granularity required (defaults to worldwide). For example, `geo: 'US-CA-800'` will target the Bakersfield, California, United States or `geo: 'US'` will just target the US. Passing `geo: ['US-CA, US-VA'], keyword: ['wine', 'peanuts']` will search for wine in California and peanuts in Virginia. 465 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 466 | for results (defaults to english) 467 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 468 | * `category` - *optional* - type `number` - a number corresponding to a particular category to query within (defaults to all categories), see the [category wiki](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) for a complete list 469 | 470 | Optional callback `function` as the second parameter (otherwise returns a promise) 471 | 472 | ##### Example 473 | Returning top related queries for 'Westminster Dog show' with default startTime, endTime, and geo categories 474 | 475 | ###### Input 476 | ```js 477 | googleTrends.relatedQueries({keyword: 'Westminster Dog Show'}) 478 | .then((res) => { 479 | console.log(res); 480 | }) 481 | .catch((err) => { 482 | console.log(err); 483 | }) 484 | ``` 485 | 486 | ###### Output 487 | ```js 488 | {"default":{"rankedList":[{"rankedKeyword":[{"query":"dog show 2016","value":100,"formattedValue":"100","link":"/"},{"query":"2016 westminster dog show","value":95,"formattedValue":"95","link":"/"}, 489 | ... 490 | {"query":"dogs","value":20,"formattedValue":"20","link":"/"}]},{"rankedKeyword":[{"query":"dog show 2016","value":836500,"formattedValue":"Breakout","link":"/"},{"query":"2016 westminster dog show","value":811550,"formattedValue":"Breakout","link":"/"}, 491 | ... 492 | {"query":"who won the westminster dog show","value":59000,"formattedValue":"Breakout","link":"/"}]}]}} 493 | ``` 494 | 495 | [back to top](#introduction) 496 | 497 |
498 | 499 | #### relatedTopics 500 | *Users searching for your term also searched for these topics* 501 | 502 | ##### Syntax 503 | `googleTrends.relatedTopics({keyword: string, startTime: Date, endTime: Date, geo: string}, cbFunc)` 504 | 505 | Requires an `object` as the first parameter with the following keys: 506 | * `keyword` - **required** - type `string` or `array` - the search term(s) of interest 507 | * `startTime` - *optional* - type `Date` object - the start of the time range of interest (defaults to `new Date('2004-01-01')` if not supplied) 508 | * `endTime` - *optional* - type `Date` object - the end of the time range of interest (defaults to `new Date(Date.now())` if not supplied) 509 | * `geo` - *optional* - type `string` or `array` - geocode(s) for a country, region, or DMA depending on the granularity required (defaults to worldwide). For example, `geo: 'US-CA-800'` will target the Bakersfield, California, United States or `geo: 'US'` will just target the US. Passing `geo: ['US-CA, US-VA'], keyword: ['wine', 'peanuts']` will search for wine in California and peanuts in Virginia. 510 | * `hl` - *optional* - type `string` - preferred language code for results (defaults to english) 511 | for results (defaults to english) 512 | * `timezone` - *optional* - type `number` - preferred timezone (defaults to the time zone difference, in minutes, from UTC to current locale (host system settings)) 513 | * `category` - *optional* - type `number` - a number corresponding to a particular category to query within (defaults to all categories), see the [category wiki](https://github.com/pat310/google-trends-api/wiki/Google-Trends-Categories) for a complete list 514 | 515 | Optional callback `function` as the second parameter (otherwise returns a promise) 516 | 517 | ##### Example 518 | Returning top related topics for 'Chipotle' from January 1st, 2015 to February 10th, 2017. 519 | 520 | ###### Input 521 | ```js 522 | googleTrends.relatedTopics({keyword: 'Chipotle', startTime: new Date('2015-01-01'), endTime: new Date('2017-02-10')}) 523 | .then((res) => { 524 | console.log(res); 525 | }) 526 | .catch((err) => { 527 | console.log(err); 528 | }) 529 | ``` 530 | 531 | ###### Output 532 | ```js 533 | {"default":{"rankedList":[{"rankedKeyword":[{"topic":{"mid":"/m/01b566","title":"Chipotle Mexican Grill","type":"Restaurant company"},"value":100,"formattedValue":"100","link":"/"},{"topic":{"mid":"/m/02f217","title":"Chipotle","type":"Jalape\u00f1o"},"value":5,"formattedValue":"5","link":"/"}, 534 | ... 535 | {"topic":{"mid":"/m/01xg7s","title":"Chorizo","type":"Topic"},"value":0,"formattedValue":"0","link":"/"}]},{"rankedKeyword":[{"topic":{"mid":"/m/09_yl","title":"E. coli","type":"Bacteria"},"value":40700,"formattedValue":"Breakout","link":"/"}, 536 | ... 537 | {"topic":{"mid":"/m/0dqc4","title":"Caridea","type":"Animal"},"value":40,"formattedValue":"+40%","link":"/"}]}]}} 538 | ``` 539 | 540 | [back to top](#introduction) 541 | 542 | 543 |
544 | 545 | 546 | 547 |
548 | 549 | ## Geo help 550 | Unfortunately support is not offered for zip codes at this time. The user must enter a country code, region (or state) code, and/or DMA (Designated Market Area) code. 551 | 552 | * A list of country codes can be found here: [country code list](https://github.com/datasets/country-codes/blob/master/data/country-codes.csv) 553 | * A list of DMAs can be found here: [DMA list](https://support.google.com/richmedia/answer/2745487?hl=en) 554 | * A list of available languages can be found here: [language codes](https://sites.google.com/site/tomihasa/google-language-codes) 555 | 556 |
557 | 558 | ## Big Thanks 559 | * To [dreyco676](https://github.com/dreyco676) for the heads up on the deprecated routes and new end points. Checkout the [python google trends](https://github.com/GeneralMills/pytrends) 560 | 561 | [back to top](#introduction) 562 | -------------------------------------------------------------------------------- /allCategories.txt: -------------------------------------------------------------------------------- 1 | {"children":[{"children":[{"name":"Celebrities \u0026 Entertainment News","id":184},{"children":[{"name":"Animated Films","id":1104},{"name":"Anime \u0026 Manga","id":317},{"name":"Cartoons","id":319},{"name":"Comics","id":318}],"name":"Comics \u0026 Animation","id":316},{"children":[{"children":[{"name":"Film \u0026 TV Awards","id":1108},{"name":"Film \u0026 TV Production","id":1117}],"name":"Film \u0026 TV Industry","id":1116},{"children":[{"name":"Music Awards","id":1113},{"name":"Record Labels","id":1114}],"name":"Recording Industry","id":1115}],"name":"Entertainment Industry","id":612},{"children":[{"name":"Clubs \u0026 Nightlife","id":188},{"name":"Concerts \u0026 Music Festivals","id":891},{"name":"Film Festivals","id":1086},{"name":"Live Sporting Events","id":1273},{"name":"Movie Listings \u0026 Theater Showtimes","id":1085},{"name":"Ticket Sales","id":614}],"name":"Events \u0026 Listings","id":569},{"children":[{"name":"Dress-Up \u0026 Fashion Games","id":1173},{"name":"Flash-Based Entertainment","id":447},{"name":"Fun Tests \u0026 Silly Surveys","id":1174}],"name":"Fun \u0026 Trivia","id":539},{"children":[{"name":"Comedy Films","id":1095},{"name":"Live Comedy","id":895},{"name":"Political Humor","id":1180},{"name":"Spoofs \u0026 Satire","id":1244},{"name":"TV Comedies","id":1047}],"name":"Humor","id":182},{"children":[{"children":[{"name":"Martial Arts Films","id":1101},{"name":"Superhero Films","id":1100},{"name":"Western Films","id":1099}],"name":"Action \u0026 Adventure Films","id":1097},{"name":"Animated Films","id":1104},{"name":"Bollywood \u0026 South Asian Film","id":360},{"children":[{"name":"Silent Films","id":1098}],"name":"Classic Films","id":1102},{"name":"Comedy Films","id":1095},{"name":"Cult \u0026 Indie Films","id":1103},{"name":"Documentary Films","id":1072},{"name":"Drama Films","id":1094},{"children":[{"name":"DVD \u0026 Video Rentals","id":1145}],"name":"DVD \u0026 Video Shopping","id":210},{"name":"Family Films","id":1291},{"name":"Film \u0026 TV Awards","id":1108},{"name":"Film Festivals","id":1086},{"name":"Horror Films","id":615},{"name":"Movie Memorabilia","id":213},{"children":[{"name":"Movie Reviews \u0026 Previews","id":1107}],"name":"Movie Reference","id":1106},{"name":"Musical Films","id":1105},{"name":"Romance Films","id":1310},{"name":"Science Fiction \u0026 Fantasy Films","id":616},{"name":"Thriller, Crime \u0026 Mystery Films","id":1096}],"name":"Movies","id":34},{"children":[{"name":"CD \u0026 Audio Shopping","id":217},{"children":[{"name":"Opera","id":1185}],"name":"Classical Music","id":586},{"name":"Country Music","id":587},{"name":"Dance \u0026 Electronic Music","id":588},{"name":"Experimental \u0026 Industrial Music","id":1022},{"name":"Folk \u0026 Traditional Music","id":1023},{"children":[{"name":"Blues","id":1040},{"name":"Jazz","id":42}],"name":"Jazz \u0026 Blues","id":589},{"name":"Latin Pop","id":1285},{"name":"Music Art \u0026 Memorabilia","id":218},{"name":"Music Education \u0026 Instruction","id":1087},{"children":[{"name":"DJ Resources \u0026 Equipment","id":1025},{"name":"Music Recording Technology","id":1026},{"children":[{"name":"Drums \u0026 Percussion","id":1327},{"name":"Guitars","id":1325},{"name":"Pianos \u0026 Keyboards","id":1326}],"name":"Musical Instruments","id":216},{"name":"Samples \u0026 Sound Libraries","id":1091}],"name":"Music Equipment \u0026 Technology","id":1024},{"children":[{"name":"Music Composition \u0026 Theory","id":1028},{"name":"Sheet Music","id":892},{"name":"Song Lyrics \u0026 Tabs","id":617}],"name":"Music Reference","id":1027},{"name":"Music Streams \u0026 Downloads","id":220},{"name":"Pop Music","id":1021},{"children":[{"name":"Podcasting","id":809},{"name":"Talk Radio","id":1186}],"name":"Radio","id":215},{"children":[{"name":"Christian \u0026 Gospel Music","id":585}],"name":"Religious Music","id":1020},{"children":[{"name":"Classic Rock \u0026 Oldies","id":1037},{"name":"Hard Rock \u0026 Progressive","id":1035},{"name":"Indie \u0026 Alternative Music","id":1038},{"name":"Metal (Music)","id":1036},{"name":"Punk (Music)","id":1041}],"name":"Rock Music","id":590},{"name":"Soundtracks","id":893},{"children":[{"name":"Rap \u0026 Hip-Hop","id":1030},{"name":"Reggaeton","id":1242},{"name":"Soul \u0026 R\u0026B","id":1039}],"name":"Urban \u0026 Hip-Hop","id":592},{"name":"Vocals \u0026 Show Tunes","id":618},{"children":[{"name":"African Music","id":1208},{"name":"Arab \u0026 Middle Eastern Music","id":1034},{"name":"East Asian Music","id":1033},{"children":[{"name":"Brazilian Music","id":1287},{"name":"Latin Pop","id":1285},{"name":"Reggaeton","id":1242},{"name":"Salsa \u0026 Tropical Music","id":1286}],"name":"Latin American Music","id":591},{"children":[{"name":"Reggaeton","id":1242}],"name":"Reggae \u0026 Caribbean Music","id":1031},{"name":"South Asian Music","id":1032}],"name":"World Music","id":593}],"name":"Music \u0026 Audio","id":35},{"children":[{"name":"Edgy \u0026 Bizarre","id":538},{"name":"Occult \u0026 Paranormal","id":449}],"name":"Offbeat","id":33},{"children":[{"name":"Flash-Based Entertainment","id":447},{"name":"Music Streams \u0026 Downloads","id":220},{"children":[{"name":"Massive Multiplayer","id":935}],"name":"Online Games","id":105},{"children":[{"name":"Photo \u0026 Image Sharing","id":978},{"name":"Photo Rating Sites","id":320},{"name":"Stock Photography","id":574}],"name":"Online Image Galleries","id":1222},{"children":[{"name":"Video Sharing","id":979}],"name":"Online Video","id":211},{"name":"Web Portals","id":301},{"name":"Webcams \u0026 Virtual Tours","id":575}],"name":"Online Media","id":613},{"children":[{"name":"Acting \u0026 Theater","id":894},{"name":"Broadway \u0026 Musical Theater","id":1243},{"name":"Dance","id":581},{"name":"Opera","id":1185}],"name":"Performing Arts","id":23},{"children":[{"children":[{"name":"Video Sharing","id":979}],"name":"Online Video","id":211},{"name":"TV Commercials","id":1055},{"name":"TV Guides \u0026 Reference","id":1187},{"name":"TV Networks \u0026 Stations","id":359},{"children":[{"name":"TV Comedies","id":1047},{"children":[{"name":"TV Crime \u0026 Legal Shows","id":1111},{"name":"TV Medical Shows","id":1194},{"name":"TV Soap Operas","id":357}],"name":"TV Dramas","id":1193},{"name":"TV Family-Oriented Shows","id":1110},{"name":"TV Game Shows","id":1050},{"name":"TV Reality Shows","id":1049},{"name":"TV Sci-Fi \u0026 Fantasy Shows","id":1112},{"name":"TV Talk Shows","id":1048}],"name":"TV Shows \u0026 Programs","id":358}],"name":"TV \u0026 Video","id":36},{"children":[{"name":"Architecture","id":477},{"name":"Art \u0026 Craft Supplies","id":1361},{"name":"Arts Education","id":1195},{"children":[{"name":"CAD \u0026 CAM","id":1300},{"name":"Graphic Design","id":654},{"name":"Industrial \u0026 Product Design","id":655},{"name":"Interior Design","id":656}],"name":"Design","id":653},{"name":"Painting","id":1167},{"children":[{"children":[{"name":"Binoculars, Telescopes \u0026 Optical Devices","id":1384},{"children":[{"name":"Camcorders","id":308},{"name":"Camera Lenses","id":1383},{"name":"Cameras","id":307}],"name":"Cameras \u0026 Camcorders","id":306}],"name":"Camera \u0026 Photo Equipment","id":573},{"children":[{"name":"Video File Formats \u0026 Codecs","id":1315}],"name":"Photo \u0026 Video Software","id":577}],"name":"Photographic \u0026 Digital Arts","id":439}],"name":"Visual Art \u0026 Design","id":24}],"name":"Arts \u0026 Entertainment","id":3},{"children":[{"name":"Automotive Industry","id":1190},{"name":"Bicycles \u0026 Accessories","id":1191},{"name":"Boats \u0026 Watercraft","id":1140},{"name":"Campers \u0026 RVs","id":1213},{"name":"Classic Vehicles","id":1013},{"children":[{"name":"Cargo Trucks \u0026 Trailers","id":1215}],"name":"Commercial Vehicles","id":1214},{"name":"Custom \u0026 Performance Vehicles","id":806},{"children":[{"name":"Electric \u0026 Plug-In Vehicles","id":1380}],"name":"Hybrid \u0026 Alternative Vehicles","id":810},{"name":"Microcars \u0026 City Cars","id":1317},{"name":"Motorcycles","id":273},{"name":"Off-Road Vehicles","id":148},{"name":"Personal Aircraft","id":1147},{"name":"Scooters \u0026 Mopeds","id":1212},{"children":[{"name":"SUVs","id":1057},{"name":"Trucks","id":1056},{"name":"Vans \u0026 Minivans","id":1058}],"name":"Trucks \u0026 SUVs","id":610},{"children":[{"name":"Acura","id":820},{"name":"Audi","id":821},{"name":"Bentley","id":1059},{"name":"BMW","id":822},{"name":"Buick","id":1060},{"name":"Cadillac","id":823},{"name":"Chevrolet","id":826},{"name":"Chrysler","id":833},{"name":"Citroën","id":834},{"name":"Dodge","id":836},{"name":"Ferrari","id":1061},{"name":"Fiat","id":838},{"name":"Ford","id":840},{"name":"GM-Daewoo","id":896},{"name":"GMC","id":842},{"name":"Honda","id":843},{"name":"Hummer","id":1062},{"name":"Hyundai","id":845},{"name":"Isuzu","id":1378},{"name":"Jaguar","id":1063},{"name":"Jeep","id":846},{"name":"Kia","id":848},{"name":"Lamborghini","id":1064},{"name":"Land Rover","id":1065},{"name":"Lexus","id":849},{"name":"Lincoln","id":850},{"name":"Maserati","id":1066},{"name":"Mazda","id":851},{"name":"Mercedes-Benz","id":852},{"name":"Mercury","id":853},{"name":"Mini","id":1067},{"name":"Mitsubishi","id":854},{"children":[{"name":"Infiniti","id":1377}],"name":"Nissan","id":855},{"name":"Peugeot","id":856},{"name":"Pontiac","id":857},{"name":"Porsche","id":858},{"name":"Renault-Samsung","id":859},{"name":"Rolls-Royce","id":1068},{"name":"Saab","id":897},{"name":"Saturn","id":860},{"name":"Subaru","id":861},{"name":"Suzuki","id":1070},{"children":[{"name":"Scion","id":1069}],"name":"Toyota","id":863},{"name":"Vauxhall-Opel","id":898},{"name":"Volkswagen","id":865},{"name":"Volvo","id":867}],"name":"Vehicle Brands","id":815},{"children":[{"name":"Drunk Driving Law","id":968}],"name":"Vehicle Codes \u0026 Driving Laws","id":1294},{"name":"Vehicle Licensing \u0026 Registration","id":170},{"name":"Vehicle Maintenance","id":138},{"children":[{"name":"Auto Exterior","id":1217},{"name":"Auto Interior","id":1218},{"children":[{"name":"Car Audio","id":230},{"name":"Car Video","id":1189},{"name":"GPS \u0026 Navigation","id":794}],"name":"Car Electronics","id":1188},{"name":"Engine \u0026 Transmission","id":1216},{"name":"Vehicle Fuels \u0026 Lubricants","id":1269},{"name":"Vehicle Wheels \u0026 Tires","id":438}],"name":"Vehicle Parts \u0026 Accessories","id":89},{"children":[{"name":"Fuel Economy \u0026 Gas Prices","id":1268},{"name":"Vehicle Specs, Reviews \u0026 Comparisons","id":1267}],"name":"Vehicle Shopping","id":473},{"name":"Vehicle Shows","id":803}],"name":"Autos \u0026 Vehicles","id":47},{"children":[{"name":"Beauty Pageants","id":1219},{"name":"Body Art","id":239},{"children":[{"name":"Cosmetic Surgery","id":238}],"name":"Cosmetic Procedures","id":1220},{"name":"Cosmetology \u0026 Beauty Professionals","id":147},{"children":[{"name":"Hygiene \u0026 Toiletries","id":244},{"name":"Make-Up \u0026 Cosmetics","id":234},{"name":"Perfumes \u0026 Fragrances","id":242},{"name":"Skin \u0026 Nail Care","id":93},{"name":"Unwanted Body \u0026 Facial Hair Removal","id":144}],"name":"Face \u0026 Body Care","id":143},{"children":[{"name":"Fashion Designers \u0026 Collections","id":98},{"name":"Fashion Modeling","id":1155}],"name":"Fashion \u0026 Style","id":185},{"children":[{"name":"Bodybuilding","id":241},{"name":"Yoga \u0026 Pilates","id":611}],"name":"Fitness","id":94},{"children":[{"name":"Hair Loss","id":235}],"name":"Hair Care","id":146},{"children":[{"name":"Massage Therapy","id":557}],"name":"Spas \u0026 Beauty Services","id":145},{"name":"Weight Loss","id":236}],"name":"Beauty \u0026 Fitness","id":44},{"children":[{"name":"Biographies \u0026 Quotations","id":690},{"name":"Book Retailers","id":355},{"name":"Children\u0027s Literature","id":1183},{"name":"E-Books","id":608},{"name":"Fan Fiction","id":540},{"name":"Literary Classics","id":1184},{"name":"Magazines","id":412},{"name":"Poetry","id":565},{"name":"Writers Resources","id":1177}],"name":"Books \u0026 Literature","id":22},{"children":[{"children":[{"children":[{"name":"Loyalty Cards \u0026 Programs","id":1309}],"name":"Marketing Services","id":83},{"name":"Public Relations","id":327},{"name":"Search Engine Optimization \u0026 Marketing","id":84},{"name":"Telemarketing","id":328}],"name":"Advertising \u0026 Marketing","id":25},{"children":[{"name":"Defense Industry","id":669},{"name":"Space Technology","id":668}],"name":"Aerospace \u0026 Defense","id":356},{"children":[{"name":"Agricultural Equipment","id":748},{"name":"Aquaculture","id":747},{"name":"Crops \u0026 Seed","id":749},{"name":"Food Production","id":621},{"name":"Forestry","id":750},{"name":"Horticulture","id":751},{"name":"Livestock","id":752}],"name":"Agriculture \u0026 Forestry","id":46},{"name":"Automotive Industry","id":1190},{"name":"Business Education","id":799},{"children":[{"name":"Commercial Lending","id":1160},{"name":"Investment Banking","id":1139},{"name":"Risk Management","id":620},{"name":"Venture Capital","id":905}],"name":"Business Finance","id":1138},{"children":[{"children":[{"name":"Company Earnings","id":1240},{"name":"Mergers \u0026 Acquisitions","id":1241}],"name":"Company News","id":1179},{"name":"Economy News","id":1164},{"name":"Financial Markets","id":1163},{"name":"Fiscal Policy News","id":1165}],"name":"Business News","id":784},{"children":[{"name":"Business Plans \u0026 Presentations","id":336},{"children":[{"name":"Compensation \u0026 Benefits","id":723},{"name":"Corporate Training","id":331},{"name":"Payroll Services","id":724},{"name":"Recruitment \u0026 Staffing","id":330}],"name":"Human Resources","id":157},{"children":[{"name":"Business Process","id":721},{"children":[{"name":"Project Management Software","id":1359}],"name":"Project Management","id":1360},{"name":"Strategic Planning","id":722},{"name":"Supply Chain Management","id":801}],"name":"Management","id":338}],"name":"Business Operations","id":1159},{"children":[{"children":[{"children":[{"name":"Loyalty Cards \u0026 Programs","id":1309}],"name":"Marketing Services","id":83},{"name":"Public Relations","id":327},{"name":"Search Engine Optimization \u0026 Marketing","id":84},{"name":"Telemarketing","id":328}],"name":"Advertising \u0026 Marketing","id":25},{"name":"Consulting","id":1162},{"children":[{"name":"Trade Shows \u0026 Conventions","id":335}],"name":"Corporate Events","id":334},{"children":[{"name":"Merchant Services \u0026 Payment Systems","id":280}],"name":"E-Commerce Services","id":340},{"name":"Fire \u0026 Security Services","id":726},{"name":"Knowledge Management","id":800},{"children":[{"name":"Office \u0026 Facilities Management","id":337}],"name":"Office Services","id":28},{"children":[{"name":"Business Cards \u0026 Stationary","id":1375},{"name":"Office Furniture","id":333},{"children":[{"name":"Copiers","id":1331},{"name":"Fax Machines","id":1332},{"name":"Ink \u0026 Toner","id":1333},{"name":"Printers","id":494},{"name":"Scanners","id":495}],"name":"Printers, Copiers \u0026 Fax","id":1330}],"name":"Office Supplies","id":95},{"name":"Outsourcing","id":718},{"children":[{"name":"Stock Photography","id":574}],"name":"Photo \u0026 Video Services","id":576},{"name":"Physical Asset Management","id":719},{"name":"Quality Control \u0026 Tracking","id":720},{"name":"Signage","id":1076},{"name":"Writing \u0026 Editing Services","id":725}],"name":"Business Services","id":329},{"children":[{"name":"Agrochemicals","id":670},{"name":"Cleaning Agents","id":671},{"name":"Coatings \u0026 Adhesives","id":672},{"name":"Dyes \u0026 Pigments","id":673},{"name":"Plastics \u0026 Polymers","id":674}],"name":"Chemicals Industry","id":288},{"children":[{"children":[{"name":"Doors \u0026 Windows","id":827},{"name":"HVAC \u0026 Climate Control","id":828},{"name":"Nails Screws \u0026 Fasteners","id":829},{"name":"Plumbing Fixtures \u0026 Equipment","id":830},{"name":"Wood \u0026 Plastics","id":831}],"name":"Building Materials \u0026 Supplies","id":650},{"name":"Civil Engineering","id":651},{"name":"Construction Consulting \u0026 Contracting","id":652},{"name":"Urban \u0026 Regional Planning","id":686}],"name":"Construction \u0026 Maintenance","id":48},{"children":[{"name":"Electricity","id":658},{"name":"Nuclear Energy","id":954},{"children":[{"name":"Vehicle Fuels \u0026 Lubricants","id":1269}],"name":"Oil \u0026 Gas","id":659},{"name":"Renewable \u0026 Alternative Energy","id":657},{"children":[{"name":"Recycling","id":1307}],"name":"Waste Management","id":660},{"name":"Water Supply \u0026 Treatment","id":1349}],"name":"Energy \u0026 Utilities","id":233},{"children":[{"name":"Customer Relationship Management (CRM)","id":341},{"name":"Data Management","id":343},{"children":[{"name":"Merchant Services \u0026 Payment Systems","id":280}],"name":"E-Commerce Services","id":340},{"name":"Enterprise Resource Planning (ERP)","id":342}],"name":"Enterprise Technology","id":77},{"children":[{"children":[{"name":"Film \u0026 TV Awards","id":1108},{"name":"Film \u0026 TV Production","id":1117}],"name":"Film \u0026 TV Industry","id":1116},{"children":[{"name":"Music Awards","id":1113},{"name":"Record Labels","id":1114}],"name":"Recording Industry","id":1115}],"name":"Entertainment Industry","id":612},{"children":[{"name":"Event Planning","id":956},{"children":[{"name":"Grocery \u0026 Food Retailers","id":121},{"name":"Restaurant Supply","id":816}],"name":"Food Service","id":957}],"name":"Hospitality Industry","id":955},{"children":[{"children":[{"name":"Valves Hoses \u0026 Fittings","id":839}],"name":"Fluid Handling","id":1152},{"name":"Generators","id":835},{"name":"Heavy Machinery","id":837}],"name":"Industrial Materials \u0026 Equipment","id":287},{"children":[{"name":"Factory Automation","id":661}],"name":"Manufacturing","id":49},{"name":"Metals \u0026 Mining","id":606},{"name":"Pharmaceuticals \u0026 Biotech","id":255},{"children":[{"children":[{"name":"Business Cards \u0026 Stationary","id":1375}],"name":"Document \u0026 Printing Services","id":332},{"name":"Journalism \u0026 News Industry","id":1204}],"name":"Printing \u0026 Publishing","id":1176},{"name":"Professional \u0026 Trade Associations","id":1199},{"children":[{"name":"Retail Equipment \u0026 Technology","id":844}],"name":"Retail Trade","id":841},{"children":[{"name":"Business Formation","id":1200},{"name":"Home Office","id":727},{"name":"MLM \u0026 Business Opportunities","id":552}],"name":"Small Business","id":551},{"name":"Textiles \u0026 Nonwovens","id":566},{"children":[{"name":"Aviation","id":662},{"name":"Distribution \u0026 Logistics","id":664},{"children":[{"name":"Cargo Trucks \u0026 Trailers","id":1215}],"name":"Freight \u0026 Trucking","id":289},{"name":"Import \u0026 Export","id":354},{"children":[{"name":"Couriers \u0026 Messengers","id":663}],"name":"Mail \u0026 Package Delivery","id":1150},{"name":"Maritime Transport","id":665},{"name":"Moving \u0026 Relocation","id":291},{"name":"Packaging","id":290},{"children":[{"name":"Airport Parking \u0026 Transportation","id":1245}],"name":"Parking","id":1306},{"name":"Public Storage","id":1347},{"name":"Rail Transport","id":666},{"name":"Urban Transport","id":667}],"name":"Transportation \u0026 Logistics","id":50}],"name":"Business \u0026 Industrial","id":12},{"children":[{"name":"CAD \u0026 CAM","id":1300},{"children":[{"children":[{"name":"Chips \u0026 Processors","id":741},{"name":"Computer Memory","id":226},{"name":"Sound \u0026 Video Cards","id":740}],"name":"Computer Components","id":717},{"children":[{"name":"CD \u0026 DVD Drives \u0026 Burners","id":1321},{"name":"CD \u0026 DVD Storage Media","id":1322},{"name":"Computer Memory","id":226},{"name":"Data Backup \u0026 Recovery","id":1323},{"name":"Flash Drives \u0026 Memory Cards","id":1318},{"name":"Hard Drives","id":1320},{"name":"Memory Card Readers","id":1319},{"name":"Network Storage","id":729}],"name":"Computer Drives \u0026 Storage","id":496},{"children":[{"name":"Computer Monitors \u0026 Displays","id":487},{"name":"Input Devices","id":493},{"children":[{"name":"Copiers","id":1331},{"name":"Fax Machines","id":1332},{"name":"Ink \u0026 Toner","id":1333},{"name":"Printers","id":494},{"name":"Scanners","id":495}],"name":"Printers, Copiers \u0026 Fax","id":1330}],"name":"Computer Peripherals","id":312},{"name":"Computer Servers","id":728},{"name":"Desktop Computers","id":309},{"name":"Hardware Modding \u0026 Tuning","id":739},{"children":[{"name":"Tablet PCs","id":1277}],"name":"Laptops \u0026 Notebooks","id":310}],"name":"Computer Hardware","id":30},{"children":[{"name":"Antivirus \u0026 Malware","id":315},{"name":"Network Security","id":344}],"name":"Computer Security","id":314},{"children":[{"children":[{"name":"Headphones","id":1396},{"name":"MP3 \u0026 Portable Media Players","id":227},{"name":"Speakers","id":1158},{"name":"Stereo Systems \u0026 Components","id":91}],"name":"Audio Equipment","id":361},{"children":[{"name":"Binoculars, Telescopes \u0026 Optical Devices","id":1384},{"children":[{"name":"Camcorders","id":308},{"name":"Camera Lenses","id":1383},{"name":"Cameras","id":307}],"name":"Cameras \u0026 Camcorders","id":306}],"name":"Camera \u0026 Photo Equipment","id":573},{"children":[{"name":"Car Audio","id":230},{"name":"Car Video","id":1189},{"name":"GPS \u0026 Navigation","id":794}],"name":"Car Electronics","id":1188},{"name":"Electronic Accessories","id":1192},{"children":[{"name":"E-Book Readers","id":1324},{"name":"Handheld Game Consoles","id":1046},{"name":"MP3 \u0026 Portable Media Players","id":227},{"name":"PDAs \u0026 Handhelds","id":228}],"name":"Gadgets \u0026 Portable Electronics","id":362},{"children":[{"name":"Handheld Game Consoles","id":1046},{"name":"Nintendo","id":1043},{"name":"Sony PlayStation","id":1044},{"name":"Xbox","id":1045}],"name":"Game Systems \u0026 Consoles","id":899},{"name":"GPS \u0026 Navigation","id":794},{"children":[{"name":"DVRs \u0026 Set-Top Boxes","id":1393},{"name":"Home Theater Systems","id":1157},{"name":"Projectors \u0026 Screens","id":1334},{"children":[{"name":"HDTVs","id":1354},{"name":"LCD TVs","id":1356},{"name":"Plasma TVs","id":1355},{"name":"Projection TVs","id":1357}],"name":"Televisions","id":305},{"children":[{"name":"Blu-Ray Players \u0026 Recorders","id":1394},{"name":"DVD Players \u0026 Recorders","id":1395}],"name":"Video Players \u0026 Recorders","id":492}],"name":"TV \u0026 Video Equipment","id":229}],"name":"Consumer Electronics","id":78},{"children":[{"name":"Data Sheets \u0026 Electronics Reference","id":900},{"name":"Electromechanical Devices","id":743},{"name":"Electronic Components","id":742},{"name":"Optoelectronics \u0026 Fiber","id":744},{"name":"Power Supplies","id":745},{"name":"Test \u0026 Measurement","id":746}],"name":"Electronics \u0026 Electrical","id":434},{"children":[{"name":"Customer Relationship Management (CRM)","id":341},{"name":"Data Management","id":343},{"children":[{"name":"Merchant Services \u0026 Payment Systems","id":280}],"name":"E-Commerce Services","id":340},{"name":"Enterprise Resource Planning (ERP)","id":342}],"name":"Enterprise Technology","id":77},{"children":[{"name":"Data Formats \u0026 Protocols","id":488},{"name":"Distributed \u0026 Parallel Computing","id":1298},{"name":"Network Monitoring \u0026 Management","id":347},{"name":"Networking Equipment","id":346},{"name":"VPN \u0026 Remote Access","id":1279}],"name":"Networking","id":311},{"children":[{"name":"C \u0026 C++","id":731},{"name":"Developer Jobs","id":802},{"name":"Development Tools","id":730},{"name":"Java","id":732},{"name":"Scripting Languages","id":733},{"name":"Windows \u0026 .NET","id":734}],"name":"Programming","id":31},{"children":[{"children":[{"name":"Accounting \u0026 Financial Software","id":1341},{"name":"Calendar \u0026 Scheduling Software","id":1358},{"name":"Presentation Software","id":1346},{"name":"Project Management Software","id":1359},{"name":"Spreadsheet Software","id":1344},{"name":"Word Processing Software","id":1345}],"name":"Business \u0026 Productivity Software","id":498},{"name":"Device Drivers","id":225},{"name":"Educational Software","id":804},{"name":"Freeware \u0026 Shareware","id":901},{"children":[{"name":"Content Management","id":808},{"name":"Internet Clients \u0026 Browsers","id":304},{"name":"Proxying \u0026 Filtering","id":902}],"name":"Internet Software","id":807},{"children":[{"name":"Ringtones \u0026 Mobile Goodies","id":532}],"name":"Mobile Apps \u0026 Add-Ons","id":1109},{"children":[{"children":[{"name":"Audio Files Formats \u0026 Codecs","id":1092}],"name":"Audio \u0026 Music Software","id":1089},{"children":[{"name":"Fonts","id":805}],"name":"Desktop Publishing","id":1088},{"name":"Graphics \u0026 Animation Software","id":486},{"name":"Media Players","id":1090},{"children":[{"name":"Video File Formats \u0026 Codecs","id":1315}],"name":"Photo \u0026 Video Software","id":577}],"name":"Multimedia Software","id":497},{"name":"Open Source","id":313},{"children":[{"name":"Linux \u0026 Unix","id":736},{"name":"Mac OS","id":735},{"name":"Mobile OS","id":1382},{"name":"Windows OS","id":737}],"name":"Operating Systems","id":303},{"name":"Software Utilities","id":224},{"name":"Web Apps \u0026 Online Tools","id":1142}],"name":"Software","id":32},{"name":"Technical Support","id":567},{"name":"Technology News","id":785}],"name":"Computers \u0026 Electronics","id":5},{"children":[{"children":[{"name":"Accounting \u0026 Financial Software","id":1341},{"name":"Tax Preparation \u0026 Planning","id":1283}],"name":"Accounting \u0026 Auditing","id":278},{"name":"Banking","id":37},{"children":[{"name":"Auto Financing","id":468},{"name":"College Financing","id":813},{"name":"Credit Cards","id":811},{"name":"Debt Management","id":812},{"name":"Home Financing","id":466}],"name":"Credit \u0026 Lending","id":279},{"name":"Currencies \u0026 Foreign Exchange","id":814},{"name":"Financial Planning","id":903},{"children":[{"name":"College Financing","id":813}],"name":"Grants \u0026 Financial Assistance","id":1282},{"children":[{"name":"Auto Insurance","id":467},{"name":"Health Insurance","id":249},{"name":"Home Insurance","id":465}],"name":"Insurance","id":38},{"children":[{"name":"Commodities \u0026 Futures Trading","id":904}],"name":"Investing","id":107},{"name":"Retirement \u0026 Pension","id":619}],"name":"Finance","id":7},{"children":[{"children":[{"name":"Beer","id":404},{"name":"Liquor","id":406},{"name":"Wine","id":405}],"name":"Alcoholic Beverages","id":277},{"name":"Candy \u0026 Sweets","id":906},{"children":[{"name":"Baked Goods","id":907},{"name":"Fruits \u0026 Vegetables","id":908},{"name":"Meat \u0026 Seafood","id":909},{"name":"Soups \u0026 Stews","id":910},{"name":"Vegetarian Cuisine","id":825},{"children":[{"name":"Asian Cuisine","id":912},{"name":"Latin American Cuisine","id":913},{"name":"Mediterranean Cuisine","id":914},{"name":"North American Cuisine","id":915}],"name":"World Cuisines","id":911}],"name":"Cooking \u0026 Recipes","id":122},{"name":"Culinary Training","id":297},{"name":"Grocery \u0026 Food Retailers","id":121},{"children":[{"name":"Coffee \u0026 Tea","id":916}],"name":"Non-Alcoholic Beverages","id":560},{"children":[{"name":"Dining Guides","id":917},{"name":"Fast Food","id":918},{"name":"Restaurant Supply","id":816}],"name":"Restaurants","id":276}],"name":"Food \u0026 Drink","id":71},{"children":[{"name":"Arcade \u0026 Coin-Op Games","id":919},{"children":[{"name":"Chess \u0026 Abstract Strategy Games","id":921},{"name":"Miniatures \u0026 Wargaming","id":922}],"name":"Board Games","id":920},{"children":[{"name":"Collectible Card Games","id":923},{"name":"Poker \u0026 Casino Games","id":924}],"name":"Card Games","id":39},{"children":[{"name":"Action \u0026 Platform Games","id":1311},{"name":"Adventure Games","id":925},{"name":"Casual Games","id":926},{"name":"Driving \u0026 Racing Games","id":927},{"name":"Fighting Games","id":928},{"children":[{"name":"Handheld Game Consoles","id":1046},{"name":"Nintendo","id":1043},{"name":"Sony PlayStation","id":1044},{"name":"Xbox","id":1045}],"name":"Game Systems \u0026 Consoles","id":899},{"children":[{"name":"Game Cheats \u0026 Hints","id":381}],"name":"Gaming Media \u0026 Reference","id":1343},{"name":"Music \u0026 Dance Games","id":929},{"name":"Shooter Games","id":930},{"name":"Simulation Games","id":931},{"name":"Sports Games","id":932},{"name":"Strategy Games","id":933},{"name":"Video Game Emulation","id":1342},{"name":"Video Game Retailers","id":1146}],"name":"Computer \u0026 Video Games","id":41},{"children":[{"name":"Drawing \u0026 Coloring","id":1397},{"name":"Dress-Up \u0026 Fashion Games","id":1173}],"name":"Family-Oriented Games \u0026 Activities","id":1290},{"children":[{"name":"Massive Multiplayer","id":935}],"name":"Online Games","id":105},{"name":"Party Games","id":936},{"name":"Puzzles \u0026 Brainteasers","id":937},{"name":"Roleplaying Games","id":622},{"children":[{"name":"Billiards","id":939},{"name":"Table Tennis","id":940}],"name":"Table Games","id":938}],"name":"Games","id":8},{"children":[{"children":[{"name":"Alzheimer\u0027s Disease","id":624}],"name":"Aging \u0026 Geriatrics","id":623},{"children":[{"name":"Acupuncture \u0026 Chinese Medicine","id":1239},{"name":"Cleansing \u0026 Detoxification","id":1238}],"name":"Alternative \u0026 Natural Medicine","id":499},{"children":[{"name":"AIDS \u0026 HIV","id":625},{"name":"Allergies","id":626},{"name":"Arthritis","id":628},{"name":"Cancer","id":429},{"name":"Cold \u0026 Flu","id":629},{"name":"Diabetes","id":630},{"name":"Ear Nose \u0026 Throat","id":1211},{"name":"Eating Disorders","id":571},{"children":[{"name":"Diabetes","id":630},{"name":"Thyroid Conditions","id":1329}],"name":"Endocrine Conditions","id":1328},{"name":"Genetic Disorders","id":941},{"name":"GERD \u0026 Digestive Disorders","id":638},{"name":"Heart \u0026 Hypertension","id":559},{"children":[{"name":"Cold \u0026 Flu","id":629},{"name":"Parasites \u0026 Parasitic Diseases","id":1262},{"children":[{"name":"AIDS \u0026 HIV","id":625}],"name":"Sexually Transmitted Diseases","id":421},{"name":"Vaccines \u0026 Immunizations","id":1263}],"name":"Infectious Diseases","id":632},{"name":"Injury","id":817},{"children":[{"name":"Alzheimer\u0027s Disease","id":624}],"name":"Neurological Disorders","id":942},{"name":"Obesity","id":818},{"children":[{"name":"Headaches \u0026 Migraines","id":631}],"name":"Pain Management","id":819},{"children":[{"name":"Asthma","id":627}],"name":"Respiratory Conditions","id":824},{"name":"Skin Conditions","id":420},{"name":"Sleep Disorders","id":633}],"name":"Health Conditions","id":419},{"name":"Health Education \u0026 Medical Training","id":254},{"name":"Health Foundations \u0026 Medical Research","id":252},{"children":[{"name":"Health Policy","id":1256}],"name":"Health News","id":1253},{"children":[{"children":[{"name":"Mobility Equipment \u0026 Accessories","id":1353}],"name":"Assistive Technology","id":1352}],"name":"Medical Devices \u0026 Equipment","id":251},{"children":[{"name":"Doctors\u0027 Offices","id":634},{"name":"Hospitals \u0026 Treatment Centers","id":250},{"children":[{"name":"Medical Tests \u0026 Exams","id":943},{"children":[{"name":"Cosmetic Surgery","id":238}],"name":"Surgery","id":944},{"name":"Vaccines \u0026 Immunizations","id":1263}],"name":"Medical Procedures","id":635},{"name":"Physical Therapy","id":500}],"name":"Medical Facilities \u0026 Services","id":256},{"children":[{"name":"Medical Photos \u0026 Illustration","id":945}],"name":"Medical Literature \u0026 Resources","id":253},{"children":[{"name":"Erectile Dysfunction","id":202}],"name":"Men\u0027s Health","id":636},{"children":[{"name":"Anxiety \u0026 Stress","id":639},{"name":"Depression","id":640},{"children":[{"name":"ADD \u0026 ADHD","id":642}],"name":"Learning \u0026 Developmental Disabilities","id":641}],"name":"Mental Health","id":437},{"children":[{"name":"Assisted Living \u0026 Long Term Care","id":649}],"name":"Nursing","id":418},{"children":[{"children":[{"name":"Cholesterol Issues","id":643}],"name":"Special \u0026 Restricted Diets","id":457},{"name":"Vitamins \u0026 Supplements","id":237}],"name":"Nutrition","id":456},{"name":"Oral \u0026 Dental Care","id":245},{"name":"Pediatrics","id":645},{"children":[{"name":"Drugs \u0026 Medications","id":646}],"name":"Pharmacy","id":248},{"children":[{"name":"Health Policy","id":1256},{"name":"Occupational Health \u0026 Safety","id":644},{"name":"Poisons \u0026 Overdoses","id":946},{"name":"Vaccines \u0026 Immunizations","id":1263}],"name":"Public Health","id":947},{"children":[{"name":"Birth Control","id":198},{"name":"Erectile Dysfunction","id":202},{"name":"Infertility","id":647},{"children":[{"name":"Pregnancy \u0026 Maternity","id":401}],"name":"OBGYN","id":558},{"name":"Sex Education \u0026 Counseling","id":536},{"name":"Sexual Enhancement","id":1236},{"children":[{"name":"AIDS \u0026 HIV","id":625}],"name":"Sexually Transmitted Diseases","id":421}],"name":"Reproductive Health","id":195},{"children":[{"name":"Drug \u0026 Alcohol Testing","id":1351},{"name":"Drug \u0026 Alcohol Treatment","id":1350},{"name":"Smoking \u0026 Smoking Cessation","id":1237},{"name":"Steroids \u0026 Performance-Enhancing Drugs","id":1235}],"name":"Substance Abuse","id":257},{"children":[{"name":"Eyeglasses \u0026 Contacts","id":1224}],"name":"Vision Care","id":246},{"children":[{"children":[{"name":"Pregnancy \u0026 Maternity","id":401}],"name":"OBGYN","id":558}],"name":"Women\u0027s Health","id":648}],"name":"Health","id":45},{"children":[{"name":"Antiques \u0026 Collectibles","id":64},{"name":"Bowling","id":1016},{"name":"Clubs \u0026 Nightlife","id":188},{"name":"Clubs \u0026 Organizations","id":189},{"children":[{"name":"Film \u0026 TV Awards","id":1108},{"name":"Lottery \u0026 Sweepstakes","id":364}],"name":"Contests, Awards \u0026 Prizes","id":1276},{"children":[{"name":"Fiber \u0026 Textile Arts","id":1230}],"name":"Crafts","id":284},{"children":[{"name":"Bicycles \u0026 Accessories","id":1191}],"name":"Cycling","id":458},{"children":[{"name":"Equestrian","id":568},{"name":"Fishing","id":462},{"name":"Hiking \u0026 Camping","id":542},{"name":"Hunting \u0026 Shooting","id":461}],"name":"Outdoors","id":688},{"name":"Paintball","id":786},{"children":[{"children":[{"name":"Animal Welfare","id":883},{"name":"Pet Food \u0026 Supplies","id":379},{"name":"Veterinarians","id":380}],"name":"Animal Products \u0026 Services","id":882},{"children":[{"name":"Birds","id":884},{"name":"Cats","id":885},{"name":"Dogs","id":886},{"name":"Exotic Pets","id":607},{"name":"Fish \u0026 Aquaria","id":887},{"name":"Horses","id":888},{"name":"Rabbits \u0026 Rodents","id":889},{"name":"Reptiles \u0026 Amphibians","id":890}],"name":"Pets","id":563},{"children":[{"name":"Insects \u0026 Entomology","id":1278},{"name":"Zoos-Aquariums-Preserves","id":1009}],"name":"Wildlife","id":119}],"name":"Pets \u0026 Animals","id":66},{"children":[{"children":[{"name":"Binoculars, Telescopes \u0026 Optical Devices","id":1384},{"children":[{"name":"Camcorders","id":308},{"name":"Camera Lenses","id":1383},{"name":"Cameras","id":307}],"name":"Cameras \u0026 Camcorders","id":306}],"name":"Camera \u0026 Photo Equipment","id":573},{"children":[{"name":"Video File Formats \u0026 Codecs","id":1315}],"name":"Photo \u0026 Video Software","id":577}],"name":"Photographic \u0026 Digital Arts","id":439},{"name":"Radio Control \u0026 Modeling","id":787},{"children":[{"name":"Personal Aircraft","id":1147}],"name":"Recreational Aviation","id":999},{"name":"Running \u0026 Walking","id":541},{"children":[{"children":[{"name":"Cards \u0026 Greetings","id":100},{"name":"Flowers","id":323},{"name":"Gifts","id":99},{"name":"Party \u0026 Holiday Supplies","id":324}],"name":"Gifts \u0026 Special Event Items","id":70},{"children":[{"name":"Birthdays \u0026 Name Days","id":1270},{"name":"Carnival \u0026 Mardi Gras","id":1246},{"children":[{"name":"Christmas","id":1078},{"name":"Easter","id":1123}],"name":"Christian Holidays","id":1274},{"name":"Halloween \u0026 October 31st","id":1079},{"name":"Islamic Holidays","id":1275},{"name":"Jewish Holidays","id":1124},{"name":"New Year","id":1271},{"name":"Thanksgiving","id":1125},{"name":"Valentine\u0027s Day","id":1122}],"name":"Holidays \u0026 Seasonal Events","id":678},{"name":"Weddings","id":293}],"name":"Special Occasions","id":977},{"children":[{"name":"Goth Subculture","id":503},{"name":"Science Fiction \u0026 Fantasy","id":676}],"name":"Subcultures \u0026 Niche Interests","id":502},{"children":[{"children":[{"name":"Boats \u0026 Watercraft","id":1140}],"name":"Boating","id":459},{"name":"Diving \u0026 Underwater Activities","id":1305},{"name":"Surf \u0026 Swim","id":689},{"name":"Water Sports","id":118}],"name":"Water Activities","id":1002}],"name":"Hobbies \u0026 Leisure","id":65},{"children":[{"children":[{"name":"Bathroom","id":1365},{"children":[{"name":"Bedding \u0026 Bed Linens","id":1369},{"name":"Beds \u0026 Headboards","id":1367},{"name":"Mattresses","id":1368}],"name":"Bedroom","id":1366}],"name":"Bed \u0026 Bath","id":948},{"children":[{"name":"Cleaning Supplies \u0026 Services","id":949}],"name":"Domestic Services","id":472},{"name":"Gardening \u0026 Landscaping","id":269},{"children":[{"name":"Major Kitchen Appliances","id":1293},{"name":"Small Kitchen Appliances","id":1292},{"name":"Water Filters \u0026 Purifiers","id":1371}],"name":"Home Appliances","id":271},{"children":[{"name":"Clocks","id":1363},{"name":"Lamps \u0026 Lighting","id":272},{"name":"Rugs \u0026 Carpets","id":1362},{"name":"Sofas \u0026 Chairs","id":1370}],"name":"Home Furnishings","id":270},{"children":[{"name":"Construction \u0026 Power Tools","id":950},{"name":"Doors \u0026 Windows","id":827},{"children":[{"name":"Rugs \u0026 Carpets","id":1362}],"name":"Flooring","id":832},{"name":"House Painting \u0026 Finishing","id":1232},{"name":"HVAC \u0026 Climate Control","id":828},{"name":"Plumbing","id":1153},{"name":"Roofing","id":1175}],"name":"Home Improvement","id":158},{"name":"Home Storage \u0026 Shelving","id":1348},{"name":"Homemaking \u0026 Interior Decor","id":137},{"name":"HVAC \u0026 Climate Control","id":828},{"children":[{"children":[{"name":"Cutlery \u0026 Cutting Accessories","id":1373}],"name":"Cookware \u0026 Diningware","id":120},{"name":"Major Kitchen Appliances","id":1293},{"name":"Small Kitchen Appliances","id":1292}],"name":"Kitchen \u0026 Dining","id":951},{"name":"Laundry","id":1364},{"name":"Nursery \u0026 Playroom","id":1372},{"name":"Pest Control","id":471},{"name":"Swimming Pools \u0026 Spas","id":952},{"name":"Yard \u0026 Patio","id":953}],"name":"Home \u0026 Garden","id":11},{"children":[{"children":[{"name":"Radio Equipment","id":1182}],"name":"Communications Equipment","id":385},{"children":[{"name":"Microblogging","id":1381},{"name":"Text \u0026 Instant Messaging","id":1379},{"name":"Voice \u0026 Video Chat","id":386}],"name":"Email \u0026 Messaging","id":394},{"children":[{"children":[{"name":"Bluetooth Accessories","id":1170}],"name":"Mobile \u0026 Wireless Accessories","id":1171},{"children":[{"name":"Ringtones \u0026 Mobile Goodies","id":532}],"name":"Mobile Apps \u0026 Add-Ons","id":1109},{"name":"Mobile OS","id":1382},{"children":[{"name":"Smart Phones","id":1071}],"name":"Mobile Phones","id":390}],"name":"Mobile \u0026 Wireless","id":382},{"children":[{"name":"People Search","id":1234}],"name":"Search Engines","id":485},{"children":[{"name":"Cable \u0026 Satellite Providers","id":501},{"name":"ISPs","id":104},{"children":[{"name":"Calling Cards","id":389}],"name":"Phone Service Providers","id":384}],"name":"Service Providers","id":383},{"name":"Teleconferencing","id":392},{"name":"Web Apps \u0026 Online Tools","id":1142},{"name":"Web Portals","id":301},{"children":[{"name":"Affiliate Programs","id":326},{"name":"Search Engine Optimization \u0026 Marketing","id":84},{"name":"Web Design \u0026 Development","id":422},{"name":"Web Hosting \u0026 Domain Registration","id":53},{"name":"Web Stats \u0026 Analytics","id":675}],"name":"Web Services","id":302}],"name":"Internet \u0026 Telecom","id":13},{"children":[{"children":[{"name":"Academic Conferences \u0026 Publications","id":1289},{"name":"Alumni \u0026 Reunions","id":1015},{"name":"Arts Education","id":1195},{"name":"Business Education","id":799},{"name":"Colleges \u0026 Universities","id":372},{"name":"Distance Learning","id":367},{"name":"Early Childhood Education","id":1012},{"name":"Foreign Language Study","id":1266},{"name":"Health Education \u0026 Medical Training","id":254},{"name":"Homeschooling","id":791},{"name":"Legal Education","id":792},{"name":"Music Education \u0026 Instruction","id":1087},{"name":"Primary \u0026 Secondary Schooling (K-12)","id":371},{"name":"Special Education","id":1118},{"name":"Standardized \u0026 Admissions Tests","id":373},{"name":"Study Abroad","id":1308},{"name":"Teaching \u0026 Classroom Resources","id":700},{"name":"Training \u0026 Certification","id":1388},{"children":[{"name":"Computer Education","id":1229}],"name":"Vocational \u0026 Continuing Education","id":369}],"name":"Education","id":74},{"children":[{"name":"Career Resources \u0026 Planning","id":959},{"name":"Developer Jobs","id":802},{"name":"Job Listings","id":960},{"name":"Resumes \u0026 Portfolios","id":961}],"name":"Jobs","id":60}],"name":"Jobs \u0026 Education","id":958},{"children":[{"children":[{"name":"Courts \u0026 Judiciary","id":1075},{"name":"Embassies \u0026 Consulates","id":962},{"name":"Executive Branch","id":963},{"name":"Government Agencies","id":1387},{"name":"Government Contracting \u0026 Procurement","id":1385},{"name":"Intelligence \u0026 Counterterrorism","id":1221},{"name":"Legislative Branch","id":964},{"name":"Lobbying","id":1386},{"name":"Multilateral Organizations","id":965},{"name":"Public Finance","id":1161},{"children":[{"name":"Drug Laws \u0026 Policy","id":1314},{"name":"Fiscal Policy News","id":1165},{"name":"Health Policy","id":1256},{"name":"Immigration Policy \u0026 Border Issues","id":1313},{"name":"International Relations","id":521}],"name":"Public Policy","id":1316},{"name":"Royalty","id":702},{"name":"State \u0026 Local Government","id":966},{"name":"Visa \u0026 Immigration","id":555}],"name":"Government","id":76},{"children":[{"name":"Accident \u0026 Personal Injury Law","id":427},{"name":"Bankruptcy","id":423},{"name":"Business \u0026 Corporate Law","id":1272},{"name":"Constitutional Law \u0026 Civil Rights","id":967},{"name":"Criminal Law","id":424},{"name":"Family Law","id":522},{"name":"Intellectual Property","id":426},{"name":"Labor \u0026 Employment Law","id":701},{"name":"Legal Education","id":792},{"name":"Legal Services","id":969},{"name":"Product Liability","id":970},{"children":[{"name":"Drunk Driving Law","id":968}],"name":"Vehicle Codes \u0026 Driving Laws","id":1294}],"name":"Legal","id":75},{"children":[{"name":"Air Force","id":1247},{"name":"Army","id":1248},{"name":"Marines","id":1250},{"name":"Military History","id":1288},{"name":"Navy","id":1249},{"name":"Veterans","id":793}],"name":"Military","id":366},{"children":[{"children":[{"name":"Corporate \u0026 Financial Crime","id":1181},{"name":"Gangs \u0026 Organized Crime","id":1312},{"name":"Prisons \u0026 Corrections","id":1284}],"name":"Crime \u0026 Justice","id":704},{"name":"Emergency Services","id":168},{"children":[{"name":"Intelligence \u0026 Counterterrorism","id":1221}],"name":"Law Enforcement","id":535},{"children":[{"name":"Health Policy","id":1256},{"name":"Occupational Health \u0026 Safety","id":644},{"name":"Poisons \u0026 Overdoses","id":946},{"name":"Vaccines \u0026 Immunizations","id":1263}],"name":"Public Health","id":947},{"name":"Security Products \u0026 Services","id":705}],"name":"Public Safety","id":166},{"children":[{"name":"Counseling Services","id":511},{"name":"Welfare \u0026 Unemployment","id":706}],"name":"Social Services","id":508}],"name":"Law \u0026 Government","id":19},{"children":[{"name":"Broadcast \u0026 Network News","id":112},{"children":[{"children":[{"name":"Company Earnings","id":1240},{"name":"Mergers \u0026 Acquisitions","id":1241}],"name":"Company News","id":1179},{"name":"Economy News","id":1164},{"name":"Financial Markets","id":1163},{"name":"Fiscal Policy News","id":1165}],"name":"Business News","id":784},{"name":"Celebrities \u0026 Entertainment News","id":184},{"children":[{"name":"Scandals \u0026 Investigations","id":1259}],"name":"Gossip \u0026 Tabloid News","id":507},{"children":[{"name":"Health Policy","id":1256}],"name":"Health News","id":1253},{"name":"Journalism \u0026 News Industry","id":1204},{"name":"Local News","id":572},{"name":"Newspapers","id":408},{"children":[{"name":"Campaigns \u0026 Elections","id":398},{"name":"Left-Wing Politics","id":410},{"name":"Media Critics \u0026 Watchdogs","id":1203},{"name":"Opinion \u0026 Commentary","id":1201},{"name":"Political Polls \u0026 Surveys","id":1202},{"name":"Right-Wing Politics","id":409}],"name":"Politics","id":396},{"name":"Sports News","id":1077},{"name":"Technology News","id":785},{"name":"Weather","id":63},{"name":"World News","id":1209}],"name":"News","id":16},{"children":[{"children":[{"name":"Microblogging","id":1381}],"name":"Blogging Resources \u0026 Services","id":504},{"children":[{"name":"Matrimonial Services","id":546},{"name":"Personals","id":102},{"name":"Photo Rating Sites","id":320}],"name":"Dating \u0026 Personals","id":55},{"name":"File Sharing \u0026 Hosting","id":321},{"name":"Forum \u0026 Chat Providers","id":191},{"children":[{"name":"Clip Art \u0026 Animated GIFs","id":1223},{"name":"Skins Themes \u0026 Wallpapers","id":578},{"name":"Social Network Apps \u0026 Add-Ons","id":847}],"name":"Online Goodies","id":43},{"name":"Online Journals \u0026 Personal Sites","id":582},{"children":[{"name":"Photo \u0026 Image Sharing","id":978},{"name":"Video Sharing","id":979}],"name":"Photo \u0026 Video Sharing","id":275},{"children":[{"name":"Social Network Apps \u0026 Add-Ons","id":847}],"name":"Social Networks","id":529},{"name":"Virtual Worlds","id":972}],"name":"Online Communities","id":299},{"children":[{"children":[{"children":[{"name":"Mobility Equipment \u0026 Accessories","id":1353}],"name":"Assistive Technology","id":1352}],"name":"Disabled \u0026 Special Needs","id":677},{"children":[{"children":[{"name":"African-Americans","id":547}],"name":"Africans \u0026 Diaspora","id":579},{"name":"Arabs \u0026 Middle Easterners","id":556},{"children":[{"name":"East Asians \u0026 Diaspora","id":549},{"name":"South Asians \u0026 Diaspora","id":528},{"name":"Southeast Asians \u0026 Pacific Islanders","id":580}],"name":"Asians \u0026 Diaspora","id":1257},{"name":"Discrimination \u0026 Identity Relations","id":1205},{"name":"Eastern Europeans","id":682},{"name":"Expatriate Communities","id":973},{"name":"Gay-Lesbian-Bisexual-Transgender","id":113},{"children":[{"name":"Native Americans","id":171}],"name":"Indigenous Peoples","id":681},{"children":[{"name":"Jewish Holidays","id":1124}],"name":"Jewish Culture","id":550},{"name":"Latinos \u0026 Latin-Americans","id":548},{"name":"Western Europeans","id":683}],"name":"Ethnic \u0026 Identity Groups","id":56},{"children":[{"name":"Etiquette","id":1304},{"children":[{"name":"Ancestry \u0026 Genealogy","id":400},{"name":"Baby \u0026 Pet Names","id":1231},{"children":[{"name":"Adoption","id":974},{"children":[{"name":"Baby Care \u0026 Hygiene","id":115}],"name":"Babies \u0026 Toddlers","id":1374},{"name":"Child Care","id":403},{"name":"Pregnancy \u0026 Maternity","id":401},{"name":"Youth Camps","id":402}],"name":"Parenting","id":58}],"name":"Family","id":1132},{"name":"Friendship","id":1134},{"children":[{"name":"Divorce \u0026 Separation","id":1261},{"name":"Weddings","id":293}],"name":"Marriage","id":1133},{"name":"Romance","id":1135},{"children":[{"name":"Divorce \u0026 Separation","id":1261}],"name":"Troubled Relationships","id":1260}],"name":"Family \u0026 Relationships","id":1131},{"children":[{"children":[{"name":"Children\u0027s Literature","id":1183},{"name":"Family Films","id":1291},{"children":[{"name":"Drawing \u0026 Coloring","id":1397},{"name":"Dress-Up \u0026 Fashion Games","id":1173}],"name":"Family-Oriented Games \u0026 Activities","id":1290},{"name":"TV Family-Oriented Shows","id":1110}],"name":"Children\u0027s Interests","id":679},{"name":"Teen Interests","id":680}],"name":"Kids \u0026 Teens","id":154},{"children":[{"name":"Astrology \u0026 Divination","id":448},{"name":"Buddhism","id":862},{"children":[{"children":[{"name":"Christmas","id":1078},{"name":"Easter","id":1123}],"name":"Christian Holidays","id":1274}],"name":"Christianity","id":864},{"name":"Hinduism","id":866},{"children":[{"name":"Islamic Holidays","id":1275}],"name":"Islam","id":868},{"name":"Judaism","id":869},{"name":"Occult \u0026 Paranormal","id":449},{"name":"Pagan \u0026 Esoteric Traditions","id":1258},{"name":"Places of Worship","id":1296},{"name":"Scientology","id":1251},{"name":"Self-Help \u0026 Motivational","id":870},{"name":"Skeptics \u0026 Non-Believers","id":975},{"name":"Spirituality","id":101},{"name":"Theology \u0026 Religious Study","id":1340}],"name":"Religion \u0026 Belief","id":59},{"name":"Seniors \u0026 Retirement","id":298},{"children":[{"name":"Animal Welfare","id":883},{"name":"Charity \u0026 Philanthropy","id":57},{"name":"Discrimination \u0026 Identity Relations","id":1205},{"name":"Drug Laws \u0026 Policy","id":1314},{"children":[{"name":"Climate Change \u0026 Global Warming","id":1255}],"name":"Environmental Issues","id":82},{"name":"Health Policy","id":1256},{"name":"Housing \u0026 Development","id":1166},{"name":"Human Rights \u0026 Liberties","id":1280},{"name":"Immigration Policy \u0026 Border Issues","id":1313},{"name":"Media Critics \u0026 Watchdogs","id":1203},{"name":"Poverty \u0026 Hunger","id":1127},{"name":"Privacy Issues","id":1281},{"name":"Reproductive Rights","id":976},{"name":"Same-Sex Marriage","id":1301},{"children":[{"name":"Labor \u0026 Employment Law","id":701},{"name":"Unions \u0026 Labor Movement","id":1121}],"name":"Work \u0026 Labor Issues","id":703}],"name":"Social Issues \u0026 Advocacy","id":54},{"children":[{"children":[{"name":"Public Speaking","id":1303}],"name":"Communications \u0026 Media Studies","id":1302},{"name":"Demographics","id":510},{"name":"Economics","id":520},{"name":"International Relations","id":521},{"name":"Psychology","id":543}],"name":"Social Sciences","id":509},{"children":[{"name":"Goth Subculture","id":503},{"name":"Science Fiction \u0026 Fantasy","id":676}],"name":"Subcultures \u0026 Niche Interests","id":502}],"name":"People \u0026 Society","id":14},{"children":[{"children":[{"name":"Animal Welfare","id":883},{"name":"Pet Food \u0026 Supplies","id":379},{"name":"Veterinarians","id":380}],"name":"Animal Products \u0026 Services","id":882},{"children":[{"name":"Birds","id":884},{"name":"Cats","id":885},{"name":"Dogs","id":886},{"name":"Exotic Pets","id":607},{"name":"Fish \u0026 Aquaria","id":887},{"name":"Horses","id":888},{"name":"Rabbits \u0026 Rodents","id":889},{"name":"Reptiles \u0026 Amphibians","id":890}],"name":"Pets","id":563},{"children":[{"name":"Insects \u0026 Entomology","id":1278},{"name":"Zoos-Aquariums-Preserves","id":1009}],"name":"Wildlife","id":119}],"name":"Pets \u0026 Animals","id":66},{"children":[{"name":"Apartments \u0026 Residential Rentals","id":378},{"name":"Commercial \u0026 Investment Real Estate","id":1178},{"name":"Property Development","id":687},{"name":"Property Inspections \u0026 Appraisals","id":463},{"name":"Property Management","id":425},{"name":"Real Estate Agencies","id":96},{"name":"Real Estate Listings","id":1080},{"name":"Timeshares \u0026 Vacation Properties","id":1081}],"name":"Real Estate","id":29},{"children":[{"children":[{"name":"Business \u0026 Personal Listings","id":377}],"name":"Directories \u0026 Listings","id":527},{"children":[{"name":"Biographies \u0026 Quotations","id":690},{"name":"Calculators \u0026 Reference Tools","id":691},{"name":"Dictionaries \u0026 Encyclopedias","id":692},{"name":"Educational Resources","id":374},{"children":[{"name":"Legal Forms","id":1137}],"name":"Forms Guides \u0026 Templates","id":693},{"name":"How-To, DIY \u0026 Expert Content","id":694},{"name":"Public Records","id":1136},{"name":"Time \u0026 Calendars","id":695}],"name":"General Reference","id":980},{"children":[{"name":"City \u0026 Local Guides","id":1014},{"children":[{"name":"Traffic \u0026 Public Transit","id":685}],"name":"Maps","id":268}],"name":"Geographic Reference","id":1084},{"children":[{"children":[{"name":"Military History","id":1288}],"name":"History","id":433},{"name":"Myth \u0026 Folklore","id":609},{"name":"Philosophy","id":1093}],"name":"Humanities","id":474},{"children":[{"name":"Dictionaries \u0026 Encyclopedias","id":692},{"children":[{"name":"Foreign Language Study","id":1266},{"name":"Translation Tools \u0026 Resources","id":1265}],"name":"Foreign Language Resources","id":1264}],"name":"Language Resources","id":108},{"name":"Libraries \u0026 Museums","id":375},{"children":[{"children":[{"name":"Public Speaking","id":1303}],"name":"Communications \u0026 Media Studies","id":1302},{"name":"Demographics","id":510},{"name":"Economics","id":520},{"name":"International Relations","id":521},{"name":"Psychology","id":543}],"name":"Social Sciences","id":509},{"children":[{"name":"Data Sheets \u0026 Electronics Reference","id":900},{"name":"Technical Support","id":567}],"name":"Technical Reference","id":1233}],"name":"Reference","id":533},{"children":[{"name":"Astronomy","id":435},{"children":[{"name":"Anatomy","id":788},{"children":[{"name":"Insects \u0026 Entomology","id":1278}],"name":"Flora \u0026 Fauna","id":981},{"name":"Genetics","id":982},{"name":"Neuroscience","id":1226}],"name":"Biological Sciences","id":440},{"name":"Chemistry","id":505},{"children":[{"name":"Computer Education","id":1229},{"name":"Distributed \u0026 Parallel Computing","id":1298},{"name":"Machine Learning \u0026 Artificial Intelligence","id":1299},{"children":[{"name":"C \u0026 C++","id":731},{"name":"Developer Jobs","id":802},{"name":"Development Tools","id":730},{"name":"Java","id":732},{"name":"Scripting Languages","id":733},{"name":"Windows \u0026 .NET","id":734}],"name":"Programming","id":31}],"name":"Computer Science","id":1227},{"children":[{"children":[{"name":"Climate Change \u0026 Global Warming","id":1255}],"name":"Atmospheric Science","id":1254},{"name":"Geology","id":443},{"name":"Paleontology","id":1169},{"name":"Water \u0026 Marine Sciences","id":441}],"name":"Earth Sciences","id":1168},{"children":[{"name":"Climate Change \u0026 Global Warming","id":1255}],"name":"Ecology \u0026 Environment","id":442},{"children":[{"name":"CAD \u0026 CAM","id":1300},{"name":"Robotics","id":1141},{"name":"Technology News","id":785}],"name":"Engineering \u0026 Technology","id":231},{"children":[{"name":"Statistics","id":1252}],"name":"Mathematics","id":436},{"name":"Physics","id":444},{"name":"Scientific Equipment","id":445},{"name":"Scientific Institutions","id":446}],"name":"Science","id":174},{"children":[{"name":"Antiques \u0026 Collectibles","id":64},{"children":[{"name":"Apparel Services","id":1228},{"name":"Athletic Apparel","id":983},{"children":[{"name":"T-Shirts","id":428}],"name":"Casual Apparel","id":984},{"name":"Children\u0027s Clothing","id":985},{"children":[{"name":"Gems \u0026 Jewelry","id":350},{"name":"Handbags \u0026 Purses","id":986},{"name":"Watches","id":987}],"name":"Clothing Accessories","id":124},{"name":"Costumes","id":988},{"children":[{"name":"Eyeglasses \u0026 Contacts","id":1224}],"name":"Eyewear","id":989},{"name":"Footwear","id":697},{"name":"Formal Wear","id":990},{"name":"Headwear","id":991},{"name":"Men\u0027s Clothing","id":992},{"name":"Outerwear","id":993},{"name":"Sleepwear","id":994},{"name":"Swimwear","id":995},{"name":"Undergarments","id":530},{"name":"Uniforms \u0026 Workwear","id":996},{"name":"Women\u0027s Clothing","id":997}],"name":"Apparel","id":68},{"name":"Auctions","id":292},{"name":"Classifieds","id":61},{"children":[{"children":[{"name":"Headphones","id":1396},{"name":"MP3 \u0026 Portable Media Players","id":227},{"name":"Speakers","id":1158},{"name":"Stereo Systems \u0026 Components","id":91}],"name":"Audio Equipment","id":361},{"children":[{"name":"Binoculars, Telescopes \u0026 Optical Devices","id":1384},{"children":[{"name":"Camcorders","id":308},{"name":"Camera Lenses","id":1383},{"name":"Cameras","id":307}],"name":"Cameras \u0026 Camcorders","id":306}],"name":"Camera \u0026 Photo Equipment","id":573},{"children":[{"name":"Car Audio","id":230},{"name":"Car Video","id":1189},{"name":"GPS \u0026 Navigation","id":794}],"name":"Car Electronics","id":1188},{"name":"Electronic Accessories","id":1192},{"children":[{"name":"E-Book Readers","id":1324},{"name":"Handheld Game Consoles","id":1046},{"name":"MP3 \u0026 Portable Media Players","id":227},{"name":"PDAs \u0026 Handhelds","id":228}],"name":"Gadgets \u0026 Portable Electronics","id":362},{"children":[{"name":"Handheld Game Consoles","id":1046},{"name":"Nintendo","id":1043},{"name":"Sony PlayStation","id":1044},{"name":"Xbox","id":1045}],"name":"Game Systems \u0026 Consoles","id":899},{"name":"GPS \u0026 Navigation","id":794},{"children":[{"name":"DVRs \u0026 Set-Top Boxes","id":1393},{"name":"Home Theater Systems","id":1157},{"name":"Projectors \u0026 Screens","id":1334},{"children":[{"name":"HDTVs","id":1354},{"name":"LCD TVs","id":1356},{"name":"Plasma TVs","id":1355},{"name":"Projection TVs","id":1357}],"name":"Televisions","id":305},{"children":[{"name":"Blu-Ray Players \u0026 Recorders","id":1394},{"name":"DVD Players \u0026 Recorders","id":1395}],"name":"Video Players \u0026 Recorders","id":492}],"name":"TV \u0026 Video Equipment","id":229}],"name":"Consumer Electronics","id":78},{"children":[{"name":"Consumer Advocacy \u0026 Protection","id":97},{"name":"Coupons \u0026 Discount Offers","id":365},{"children":[{"name":"Loyalty Cards \u0026 Programs","id":1309},{"name":"Technical Support","id":567},{"name":"Warranties \u0026 Service Contracts","id":451}],"name":"Customer Services","id":450},{"children":[{"name":"Price Comparisons","id":352},{"name":"Vehicle Specs, Reviews \u0026 Comparisons","id":1267}],"name":"Product Reviews \u0026 Price Comparisons","id":353}],"name":"Consumer Resources","id":69},{"children":[{"name":"Book Retailers","id":355},{"name":"CD \u0026 Audio Shopping","id":217},{"children":[{"name":"DVD \u0026 Video Rentals","id":1145}],"name":"DVD \u0026 Video Shopping","id":210},{"children":[{"name":"DVD \u0026 Video Rentals","id":1145}],"name":"Entertainment Media Rentals","id":1144},{"name":"Video Game Retailers","id":1146}],"name":"Entertainment Media","id":1143},{"children":[{"name":"Cards \u0026 Greetings","id":100},{"name":"Flowers","id":323},{"name":"Gifts","id":99},{"name":"Party \u0026 Holiday Supplies","id":324}],"name":"Gifts \u0026 Special Event Items","id":70},{"name":"Luxury Goods","id":696},{"name":"Mass Merchants \u0026 Department Stores","id":73},{"children":[{"name":"Stock Photography","id":574}],"name":"Photo \u0026 Video Services","id":576},{"name":"Shopping Portals \u0026 Search Engines","id":531},{"children":[{"name":"Bicycles \u0026 Accessories","id":1191},{"name":"Sports Memorabilia","id":1083}],"name":"Sporting Goods","id":263},{"name":"Swap Meets \u0026 Outdoor Markets","id":1210},{"name":"Ticket Sales","id":614},{"name":"Tobacco Products","id":123},{"name":"Toys","id":432},{"name":"Wholesalers \u0026 Liquidators","id":1225}],"name":"Shopping","id":18},{"children":[{"name":"College Sports","id":1073},{"children":[{"name":"Boxing","id":515},{"name":"Martial Arts","id":516},{"name":"Wrestling","id":512}],"name":"Combat Sports","id":514},{"children":[{"name":"Drag \u0026 Street Racing","id":1206},{"name":"Stunts \u0026 Dangerous Feats","id":1207}],"name":"Extreme Sports","id":554},{"name":"Fantasy Sports","id":998},{"children":[{"name":"Bowling","id":1016},{"children":[{"name":"Bicycles \u0026 Accessories","id":1191}],"name":"Cycling","id":458},{"name":"Golf","id":261},{"name":"Gymnastics","id":519},{"children":[{"name":"Tennis","id":1376}],"name":"Racquet Sports","id":262},{"name":"Running \u0026 Walking","id":541},{"name":"Skate Sports","id":1126},{"name":"Track \u0026 Field","id":518}],"name":"Individual Sports","id":1000},{"name":"Live Sporting Events","id":1273},{"children":[{"name":"Drag \u0026 Street Racing","id":1206}],"name":"Motor Sports","id":180},{"children":[{"name":"Bicycles \u0026 Accessories","id":1191},{"name":"Sports Memorabilia","id":1083}],"name":"Sporting Goods","id":263},{"name":"Sports Coaching \u0026 Training","id":1082},{"name":"Sports News","id":1077},{"children":[{"name":"American Football","id":258},{"name":"Baseball","id":259},{"name":"Basketball","id":264},{"name":"Cheerleading","id":534},{"name":"Cricket","id":296},{"name":"Handball","id":1017},{"name":"Hockey","id":260},{"name":"Rugby","id":517},{"name":"Soccer","id":294},{"name":"Volleyball","id":699}],"name":"Team Sports","id":1001},{"name":"Water Sports","id":118},{"children":[{"name":"Ice Skating","id":1149},{"name":"Skiing \u0026 Snowboarding","id":1148}],"name":"Winter Sports","id":265},{"children":[{"name":"Olympics","id":513}],"name":"World Sports Competitions","id":1198}],"name":"Sports","id":20},{"children":[{"children":[{"name":"Airport Parking \u0026 Transportation","id":1245},{"children":[{"name":"Personal Aircraft","id":1147}],"name":"Recreational Aviation","id":999}],"name":"Air Travel","id":203},{"name":"Bus \u0026 Rail","id":708},{"name":"Car Rental \u0026 Taxi Services","id":205},{"name":"Carpooling \u0026 Ridesharing","id":1339},{"name":"Cruises \u0026 Charters","id":206},{"name":"Hotels \u0026 Accommodations","id":179},{"name":"Luggage \u0026 Travel Accessories","id":1003},{"children":[{"name":"Adventure Travel","id":707},{"name":"Agritourism","id":1389},{"name":"Ecotourism","id":1005},{"name":"Sightseeing Tours","id":1390},{"name":"Vineyards \u0026 Wine Tourism","id":1391}],"name":"Specialty Travel","id":1004},{"children":[{"name":"Beaches \u0026 Islands","id":1074},{"name":"Historical Sites \u0026 Buildings","id":1006},{"name":"Lakes \u0026 Rivers","id":1120},{"name":"Mountain \u0026 Ski Resorts","id":1119},{"name":"Regional Parks \u0026 Gardens","id":1007},{"name":"Theme Parks","id":1008},{"name":"Zoos-Aquariums-Preserves","id":1009}],"name":"Tourist Destinations","id":208},{"children":[{"name":"Tourist Boards \u0026 Visitor Centers","id":1392},{"name":"Vacation Offers","id":1019}],"name":"Travel Agencies \u0026 Services","id":1010},{"name":"Travel Guides \u0026 Travelogues","id":1011}],"name":"Travel","id":67}],"name":"All categories","id":0} -------------------------------------------------------------------------------- /examples.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // var googleTrends = require('./lib/google-trends-api.min.js'); 4 | 5 | /* ******************* Autocomplete **************************/ 6 | 7 | // googleTrends.autoComplete({keyword: 'Back to school'}) 8 | // .then((res) => { 9 | // console.log('this is res', res); 10 | // }) 11 | // .catch((err) => { 12 | // console.log('got the error', err); 13 | // console.log('error message', err.message); 14 | // console.log('request body', err.requestBody); 15 | // }); 16 | 17 | /* ******************* Interest over time **************************/ 18 | 19 | // googleTrends.interestOverTime({keyword: 'Valentines Day'}) 20 | // .then((res) => { 21 | // console.log('this is res', res); 22 | // }) 23 | // .catch((err) => { 24 | // console.log('got the error', err); 25 | // console.log('error message', err.message); 26 | // console.log('request body', err.requestBody); 27 | // }); 28 | 29 | // googleTrends.interestOverTime({ 30 | // keyword: 'Valentines Day', 31 | // startTime: new Date(Date.now() - (4 * 60 * 60 * 1000)), 32 | // granularTimeResolution: true, 33 | // }, function(err, results) { 34 | // if (err) console.log('oh no error!', err); 35 | // else console.log(results); 36 | // }); 37 | 38 | /* ****** Interest over time - Set a custom timezone ***************/ 39 | 40 | // googleTrends.interestOverTime({ 41 | // keyword: 'Valentines Day', 42 | // timezone: new Date().getTimezoneOffset() / 60, 43 | // }, function(err, results) { 44 | // if (err) console.log('oh no error!', err); 45 | // else console.log(results); 46 | // }); 47 | 48 | /* ****** Interest over time - Comparing multiple keywords *********/ 49 | // googleTrends.interestOverTime({keyword: ['Valentines Day', 'Christmas Day']}) 50 | // .then((res) => { 51 | // console.log('this is res', res); 52 | // }) 53 | // .catch((err) => { 54 | // console.log('got the error', err); 55 | // }) 56 | 57 | /* ******************* Interest by region **************************/ 58 | 59 | // googleTrends.interestByRegion({ 60 | // keyword: 'Donald Trump', 61 | // startTime: new Date('2017-02-01'), 62 | // endTime: new Date('2017-02-06'), 63 | // resolution: 'CITY', 64 | // }) 65 | // .then((res) => { 66 | // console.log(res); 67 | // }) 68 | // .catch((err) => { 69 | // console.log(err); 70 | // }) 71 | 72 | // googleTrends.interestByRegion({ 73 | // keyword: 'Donald Trump', 74 | // startTime: new Date('2017-02-01'), 75 | // endTime: new Date('2017-02-06'), 76 | // geo: 'US-CA', 77 | // }) 78 | // .then((res) => { 79 | // console.log(res); 80 | // }) 81 | // .catch((err) => { 82 | // console.log(err); 83 | // }) 84 | 85 | /* ******************* Related queries **************************/ 86 | 87 | // googleTrends.relatedQueries({keyword: 'Westminster Dog Show'}) 88 | // .then((res) => { 89 | // console.log(res); 90 | // }) 91 | // .catch((err) => { 92 | // console.log(err); 93 | // }) 94 | 95 | /* ******************* Related topics **************************/ 96 | 97 | // googleTrends.relatedTopics({ 98 | // keyword: 'Chipotle', 99 | // startTime: new Date('2015-01-01'), 100 | // endTime: new Date('2017-02-10'), 101 | // }) 102 | // .then((res) => { 103 | // console.log(res); 104 | // }) 105 | // .catch((err) => { 106 | // console.log(err); 107 | // }); 108 | 109 | /* ************************* RealTime Trending Searches ******************/ 110 | // googleTrends.realTimeTrends({ 111 | // geo: 'US', 112 | // category: 'all', 113 | // }, function(err, results) { 114 | // if (err) console.log('oh no error!', err); 115 | // else console.log(results); 116 | // }); 117 | 118 | /* *********************** Daily Trends *******************************/ 119 | // Please note that google only keeps around T-15 days of daily trends information. 120 | // TrendDate designation that go too far back in the past will result in an error. 121 | // Note: TrendDate is optional and will default to currentDate 122 | 123 | // googleTrends.dailyTrends({ 124 | // trendDate: new Date('2019-01-10'), 125 | // geo: 'US', 126 | // }, function(err, results) { 127 | // if (err) { 128 | // console.log('oh no error!', err); 129 | // }else{ 130 | // console.log(results); 131 | // } 132 | // }); 133 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "google-trends-api", 3 | "version": "4.9.2", 4 | "description": "an API layer on top of google trends", 5 | "main": "lib/google-trends-api.min.js", 6 | "scripts": { 7 | "build": "webpack --mode=build", 8 | "dev": "webpack --progress --colors --watch --mode=dev", 9 | "start": "npm run dev", 10 | "test": "mocha --compilers js:babel-core/register --colors ./test/*.spec.js", 11 | "test:watch": "mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js", 12 | "cover": "nyc --reporter=lcov mocha --compilers js:babel-core/register --colors ./test/*.spec.js", 13 | "coveralls": "npm run cover && nyc report --reporter=text-lcov | coveralls", 14 | "coverage": "nyc mocha --compilers js:babel-core/register --colors ./test/*.spec.js", 15 | "preversion": "npm run build", 16 | "lint:eslint": "eslint src, test", 17 | "lint:staged": "lint-staged" 18 | }, 19 | "lint-staged": { 20 | "*.js": "lint:eslint" 21 | }, 22 | "pre-commit": "lint:staged", 23 | "repository": { 24 | "type": "git", 25 | "url": "git+https://github.com/pat310/google-trends-api.git" 26 | }, 27 | "keywords": [ 28 | "google", 29 | "trends", 30 | "API", 31 | "keyword", 32 | "search", 33 | "google-trends" 34 | ], 35 | "author": "Patrick Trasborg (http://trasb.org)", 36 | "license": "MIT", 37 | "bugs": { 38 | "url": "https://github.com/pat310/google-trends-api/issues" 39 | }, 40 | "files": [ 41 | "src/*" 42 | ], 43 | "homepage": "https://github.com/pat310/google-trends-api#readme", 44 | "dependencies": {}, 45 | "devDependencies": { 46 | "babel": "6.3.13", 47 | "babel-core": "6.1.18", 48 | "babel-eslint": "5.0.0", 49 | "babel-loader": "6.1.0", 50 | "babel-plugin-add-module-exports": "0.1.2", 51 | "babel-plugin-transform-es2015-destructuring": "^6.23.0", 52 | "babel-plugin-transform-object-rest-spread": "^6.23.0", 53 | "babel-preset-es2015": "6.3.13", 54 | "chai": "3.4.1", 55 | "coveralls": "^2.11.15", 56 | "eslint": "1.7.2", 57 | "eslint-loader": "1.1.0", 58 | "istanbul": "^0.4.5", 59 | "json-loader": "^0.5.4", 60 | "lint-staged": "^4.0.3", 61 | "mocha": "2.3.4", 62 | "mocha-lcov-reporter": "^1.2.0", 63 | "nyc": "^10.1.2", 64 | "pre-commit": "^1.2.2", 65 | "webpack": "1.12.9", 66 | "yargs": "3.32.0" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/api.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export default (request, searchType, { processor, objectConstructor }) => { 4 | const resultsPromise = processor(request); 5 | 6 | return (reqObj, cb) => { 7 | const { 8 | cbFunc, 9 | obj, 10 | } = objectConstructor(reqObj, cb); 11 | 12 | if (obj instanceof Error) return Promise.reject(cbFunc(obj)); 13 | 14 | return resultsPromise(searchType, obj) 15 | .then(res => cbFunc(null, res)) 16 | .catch(err => Promise.reject(cbFunc(err))); 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import api from './api'; 3 | import request from './request'; 4 | import { getInterestResults, getTrendingResults, 5 | constructInterestObj, constructTrendingObj } from './utilities'; 6 | 7 | const interestHandler = { 8 | processor: getInterestResults, 9 | objectConstructor: constructInterestObj, 10 | }; 11 | 12 | const trendHandler = { 13 | processor: getTrendingResults, 14 | objectConstructor: constructTrendingObj, 15 | }; 16 | 17 | const apiRequest = api.bind(this, request); 18 | 19 | export default { 20 | autoComplete: apiRequest('Auto complete', interestHandler), 21 | dailyTrends: apiRequest('Daily trends', trendHandler), 22 | interestByRegion: apiRequest('Interest by region', interestHandler), 23 | interestOverTime: apiRequest('Interest over time', interestHandler), 24 | realTimeTrends: apiRequest('Real time trends', trendHandler), 25 | relatedQueries: apiRequest('Related queries', interestHandler), 26 | relatedTopics: apiRequest('Related topics', interestHandler), 27 | }; 28 | -------------------------------------------------------------------------------- /src/request.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import https from 'https'; 3 | import querystring from 'querystring'; 4 | 5 | // cache of the cookie - avoid re-requesting on subsequent requests. 6 | let cookieVal; 7 | 8 | // simpler request method for avoiding double-promise confusion 9 | function rereq(options, done) { 10 | let req; 11 | 12 | req = https.request(options, (res) => { 13 | let chunk = ''; 14 | 15 | res.on('data', (data) => { 16 | chunk += data; 17 | }); 18 | res.on('end', () => { 19 | done(null, chunk.toString('utf8')); 20 | }); 21 | }); 22 | req.on('error', (e) => { 23 | done(e); 24 | }); 25 | req.end(); 26 | } 27 | 28 | export default function request({method, host, path, qs, agent}) { 29 | const options = { 30 | host, 31 | method, 32 | path: `${path}?${querystring.stringify(qs)}`, 33 | }; 34 | 35 | if (agent) options.agent = agent; 36 | // will use cached cookieVal if set on 429 error 37 | if (cookieVal) options.headers = {'cookie': cookieVal}; 38 | 39 | return new Promise((resolve, reject) => { 40 | const req = https.request(options, (res) => { 41 | let chunk = ''; 42 | 43 | res.on('data', (data) => { 44 | chunk += data; 45 | }); 46 | 47 | res.on('end', () => { 48 | if (res.statusCode === 429 && res.headers['set-cookie']) { 49 | // Fix for the "too many requests" issue 50 | // Look for the set-cookie header and re-request 51 | cookieVal = res.headers['set-cookie'][0].split(';')[0]; 52 | options.headers = {'cookie': cookieVal}; 53 | rereq(options, function(err, response) { 54 | if (err) return reject(err); 55 | resolve(response); 56 | }); 57 | } else { 58 | resolve(chunk.toString('utf8')); 59 | } 60 | }); 61 | }); 62 | 63 | req.on('error', (e) => { 64 | reject(e); 65 | }); 66 | 67 | req.end(); 68 | }); 69 | } 70 | -------------------------------------------------------------------------------- /src/utilities.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | export function isLessThan7Days(date1, date2) { 3 | return (Math.abs(date2 - date1) / (24 * 60 * 60 * 1000)) < 7; 4 | } 5 | 6 | export function convertDateToString(d, shouldIncludeTime, formatWithoutDashes) { 7 | let month = (d.getUTCMonth() + 1).toString(); 8 | let day = d.getUTCDate().toString(); 9 | 10 | const dash = formatWithoutDashes ? '' : '-'; 11 | 12 | month = month.length < 2 ? '0' + month : month; 13 | day = formatWithoutDashes && day.length < 2 ? '0' + day : day; 14 | 15 | const year = d.getUTCFullYear().toString(); 16 | const hour = d.getUTCHours(); 17 | const minute = d.getUTCMinutes(); 18 | 19 | if (shouldIncludeTime) { 20 | return `${year}${dash}${month}${dash}${day}T${hour}\\:${minute}\\:00`; 21 | } 22 | 23 | return `${year}${dash}${month}${dash}${day}`; 24 | } 25 | 26 | export function formatTime(obj) { 27 | if (obj.startTime && obj.endTime && obj.startTime > obj.endTime) { 28 | const temp = obj.startTime; 29 | 30 | obj.startTime = obj.endTime; 31 | obj.endTime = temp; 32 | } 33 | 34 | if (!obj.endTime) obj.endTime = new Date(); 35 | if (!obj.startTime) obj.startTime = new Date('2004-01-01'); 36 | 37 | const shouldIncludeTime = isLessThan7Days(obj.startTime, obj.endTime); 38 | 39 | const startTime = convertDateToString(obj.startTime, 40 | shouldIncludeTime && obj.granularTimeResolution); 41 | const endTime = convertDateToString(obj.endTime, 42 | shouldIncludeTime && obj.granularTimeResolution); 43 | 44 | obj.time = `${startTime} ${endTime}`; 45 | return obj; 46 | } 47 | 48 | function validateGeo(obj) { 49 | const multiGeoKeyword = Array.isArray(obj.geo) && Array.isArray(obj.keyword); 50 | 51 | if (multiGeoKeyword && obj.geo.length !== obj.keyword.length) { 52 | return new Error('Geo length must be equal to keyword length'); 53 | } 54 | 55 | return obj; 56 | } 57 | 58 | function validateTime(obj) { 59 | if (obj.startTime && !(obj.startTime instanceof Date)) { 60 | obj = new Error('startTime must be a Date object'); 61 | } 62 | 63 | if (obj.endTime && !(obj.endTime instanceof Date)) { 64 | obj = new Error('endTime must be a Date object'); 65 | } 66 | 67 | return obj; 68 | } 69 | 70 | const invalidCb = cb => !!cb && typeof cb !== 'function'; 71 | 72 | function validateObj(obj, cbFunc) { 73 | if (!obj) { 74 | obj = new Error('Must supply an object'); 75 | } else if (!!obj && typeof obj !== 'object' || Array.isArray(obj)) { 76 | obj = new Error('Must supply an object'); 77 | } else if (!obj.keyword) { 78 | obj = new Error('Must have a keyword field'); 79 | } 80 | 81 | if (invalidCb(cbFunc)) { 82 | obj = new Error('Callback function must be a function'); 83 | } 84 | 85 | obj = validateGeo(obj); 86 | obj = validateTime(obj); 87 | 88 | return obj; 89 | } 90 | 91 | /** 92 | * Validates the obj and callback 93 | * and sets defaults for anything that haven't been supplied 94 | * @param {Object} obj - the object with .keyword property 95 | * @param {Function} cb - an optional callback function 96 | * @return {Object} - object with decorated obj and cbFunc properties 97 | */ 98 | export function constructInterestObj(obj, cbFunc) { 99 | 100 | if (typeof obj === 'function') cbFunc = obj; 101 | 102 | obj = validateObj(obj, cbFunc); 103 | 104 | if (!obj.hl) obj.hl = 'en-US'; 105 | if (!obj.category) obj.category = 0; 106 | if (!obj.timezone) obj.timezone = new Date().getTimezoneOffset(); 107 | 108 | const possibleProperties = ['images', 'news', 'youtube', 'froogle', '']; 109 | 110 | if (possibleProperties.indexOf(obj.property) === -1) { 111 | obj.property = ''; 112 | } 113 | 114 | if (!cbFunc) { 115 | cbFunc = (err, res) => { 116 | if (err) return err; 117 | return res; 118 | }; 119 | } 120 | 121 | obj = formatTime(obj); 122 | 123 | return { 124 | cbFunc, 125 | obj, 126 | }; 127 | } 128 | 129 | export function formatResolution(resolution = '') { 130 | const resolutions = ['COUNTRY', 'REGION', 'CITY', 'DMA']; 131 | const isResValid = resolutions.some((res) => { 132 | return res === resolution.toUpperCase(); 133 | }); 134 | 135 | if (isResValid) return resolution.toUpperCase(); 136 | return ''; 137 | } 138 | 139 | /** 140 | * Parse the result of the google api as JSON 141 | * Throws an Error if the JSON is invalid 142 | * @param {String} results 143 | * @return {Object} 144 | */ 145 | export function parseResults(results) { 146 | // If this fails, you've hit the rate limit or Google has changed something 147 | try { 148 | return JSON.parse(results.slice(4)).widgets; 149 | } catch (e) { 150 | // Throw the JSON error e.g. 151 | // { message: 'Unexpected token C in JSON at position 0', 152 | // requestBody: '...'} 153 | e.requestBody = results; 154 | throw e; 155 | } 156 | } 157 | 158 | /** 159 | * Create the array of comparisonItems to be used 160 | * @param {Object} obj The query obj with .keyword property and optionally 161 | * the .geo property 162 | * @return {Array} Returns an array of comparisonItems 163 | */ 164 | export function formatComparisonItems(obj) { 165 | const isMultiRegion = obj.geo && Array.isArray(obj.geo); 166 | let isMultiKeyword = Array.isArray(obj.keyword); 167 | 168 | // Duplicate keywords to match the length of geo 169 | if (isMultiRegion && !isMultiKeyword) { 170 | obj.keyword = Array(obj.geo.length).fill(obj.keyword); 171 | isMultiKeyword = true; 172 | } 173 | 174 | // If we are requesting an array of keywords for comparison 175 | if (isMultiKeyword) { 176 | 177 | // Map the keywords to the items array 178 | let items = obj.keyword.reduce((arr, keyword) => { 179 | // Add the keyword to the array 180 | arr.push({ ...obj, keyword }); 181 | 182 | return arr; 183 | }, []); 184 | 185 | // Is there an array of regions as well? 186 | if (isMultiRegion) { 187 | 188 | obj.geo.forEach((region, index) => { 189 | items[index].geo = region; 190 | }); 191 | } 192 | 193 | return items; 194 | } 195 | 196 | return [obj]; 197 | } 198 | 199 | export function getInterestResults(request) { 200 | return (searchType, obj) => { 201 | const map = { 202 | 'Auto complete': { 203 | path: `/trends/api/autocomplete/${encodeURIComponent(obj.keyword)}`, 204 | }, 205 | 'Interest over time': { 206 | path: '/trends/api/widgetdata/multiline', 207 | _id: 'TIMESERIES', 208 | }, 209 | 'Interest by region': { 210 | path: '/trends/api/widgetdata/comparedgeo', 211 | resolution: formatResolution(obj.resolution), 212 | _id: 'GEO_MAP', 213 | }, 214 | 'Related topics': { 215 | path: '/trends/api/widgetdata/relatedsearches', 216 | _id: 'RELATED_TOPICS', 217 | }, 218 | 'Related queries': { 219 | path: '/trends/api/widgetdata/relatedsearches', 220 | _id: 'RELATED_QUERIES', 221 | }, 222 | }; 223 | 224 | const options = { 225 | method: 'GET', 226 | host: 'trends.google.com', 227 | path: '/trends/api/explore', 228 | qs: { 229 | hl: obj.hl, 230 | req: JSON.stringify({ 231 | comparisonItem: formatComparisonItems(obj), 232 | category: obj.category, 233 | property: obj.property, 234 | }), 235 | tz: obj.timezone, 236 | }, 237 | }; 238 | 239 | if (obj.agent) options.agent = obj.agent; 240 | 241 | const { path, resolution, _id } = map[searchType]; 242 | 243 | return request(options) 244 | .then((results) => { 245 | const parsedResults = parseResults(results); 246 | 247 | /** 248 | * Search for the id that matches the search result 249 | * Auto complete does not have results on initial query 250 | * so just pass the first available result with request 251 | */ 252 | const resultObj = parsedResults.find(({ id = '', request }) => { 253 | return id.indexOf(_id) > -1 || 254 | (searchType === 'Auto complete' && request); 255 | }); 256 | 257 | if (!resultObj) { 258 | const errObj = { 259 | message: 'Available widgets does not contain selected api type', 260 | requestBody: results, 261 | }; 262 | 263 | throw errObj; 264 | } 265 | 266 | let req = resultObj.request; 267 | const token = resultObj.token; 268 | 269 | if (resolution) req.resolution = resolution; 270 | req.requestOptions.category = obj.category; 271 | req.requestOptions.property = obj.property; 272 | req = JSON.stringify(req); 273 | 274 | const nextOptions = { 275 | path, 276 | method: 'GET', 277 | host: 'trends.google.com', 278 | qs: { 279 | hl: obj.hl, 280 | req, 281 | token, 282 | tz: obj.timezone, 283 | }, 284 | }; 285 | 286 | if (obj.agent) nextOptions.agent = obj.agent; 287 | 288 | return request(nextOptions); 289 | }) 290 | .then((res) => { 291 | try { 292 | /** JSON.parse will decode unicode */ 293 | const results = JSON.stringify(JSON.parse(res.slice(5))); 294 | 295 | return results; 296 | } catch (e) { 297 | /** throws if not valid JSON, so just return unaltered res string */ 298 | return res; 299 | } 300 | }); 301 | }; 302 | } 303 | 304 | export function getTrendingResults(request) { 305 | return (searchType, obj) => { 306 | const searchTypeMap = { 307 | 'Daily trends': { 308 | path: '/trends/api/dailytrends', 309 | extraParams: { 310 | ed: convertDateToString(obj.trendDate, false, true), 311 | ns: obj.ns, 312 | }, 313 | }, 314 | 'Real time trends': { 315 | path: '/trends/api/realtimetrends', 316 | extraParams: { 317 | fi: 0, 318 | fs: 0, 319 | ri: 300, // # of trending stories IDs returned 320 | rs: 20, 321 | sort: 0, 322 | }, 323 | }, 324 | }; 325 | 326 | const options = { 327 | method: 'GET', 328 | host: 'trends.google.com', 329 | path: searchTypeMap[searchType].path, 330 | qs: { 331 | hl: obj.hl, 332 | tz: obj.timezone, 333 | geo: obj.geo, 334 | cat: obj.category, 335 | }, 336 | }; 337 | 338 | if (obj.agent) options.agent = obj.agent; 339 | 340 | options.qs = {...options.qs, ...searchTypeMap[searchType].extraParams}; 341 | 342 | return request(options) 343 | .then((res) => { 344 | try { 345 | /** JSON.parse will decode unicode */ 346 | return JSON.stringify(JSON.parse(res.slice(5))); 347 | } catch (e) { 348 | /** throws if not valid JSON, so just return unaltered res string */ 349 | return res; 350 | } 351 | }); 352 | }; 353 | } 354 | 355 | export function constructTrendingObj(obj, cbFunc) { 356 | if (typeof obj === 'function') cbFunc = obj; 357 | 358 | if (!obj || !!obj && typeof obj !== 'object' || Array.isArray(obj)) { 359 | obj = new Error('Must supply an object'); 360 | } else { 361 | if (!obj.trendDate || !(obj.trendDate instanceof Date)) { 362 | delete obj.trendDate; 363 | } 364 | 365 | const date = new Date(); 366 | const defaults = { hl: 'en-US', 367 | category: 'all', 368 | timezone: date.getTimezoneOffset(), 369 | trendDate: date, 370 | ns: 15, 371 | }; 372 | 373 | obj = { ...defaults, ...obj }; // Merge user params into obj with defaults 374 | } 375 | 376 | if (invalidCb(cbFunc)) { 377 | obj = new Error('Callback function must be a function'); 378 | } 379 | 380 | if (!obj.geo) { 381 | obj = new Error('Must supply an geographical location (geo)'); 382 | } 383 | 384 | if (!cbFunc) { 385 | cbFunc = (err, res) => { 386 | if (err) return err; 387 | return res; 388 | }; 389 | } 390 | 391 | return { 392 | cbFunc, 393 | obj, 394 | }; 395 | } 396 | -------------------------------------------------------------------------------- /test/api.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import chai from 'chai'; 3 | import api from '../src/api'; 4 | import { getInterestResults, constructInterestObj } from '../src/utilities'; 5 | 6 | const interestHandler = { 7 | processor: getInterestResults, 8 | objectConstructor: constructInterestObj, 9 | }; 10 | 11 | const expect = chai.expect; 12 | 13 | describe('api', () => { 14 | let count = 0; 15 | 16 | function request(counter) { 17 | return new Promise((resolve, reject) => { 18 | const fakeReqObj = { 19 | widgets: [{ 20 | request: { 21 | requestOptions: {}, 22 | }, 23 | title: 'Interest over time', 24 | id: 'TIMESERIES', 25 | token: 'dogman', 26 | }], 27 | }; 28 | 29 | setTimeout(() => { 30 | if (count === 0) { 31 | count += 1; 32 | resolve(`1234${JSON.stringify(fakeReqObj)}`); 33 | } else { 34 | resolve(`12345${JSON.stringify(fakeReqObj)}`); 35 | } 36 | }, 0); 37 | }); 38 | } 39 | 40 | const newFunc = api(request, 'Interest over time', interestHandler); 41 | 42 | it('should return a function', () => { 43 | expect(newFunc).to.be.a('function'); 44 | }); 45 | 46 | it('should reject if request object is not provided', (done) => { 47 | newFunc() 48 | .then((res) => { 49 | expect(res).to.not.exist; 50 | done(); 51 | }) 52 | .catch((e) => { 53 | expect(e).to.exist; 54 | done(); 55 | }); 56 | }); 57 | 58 | it('should work without a callback function', (done) => { 59 | /** reset counter */ 60 | count = 0; 61 | 62 | newFunc({keyword: 'Brooklyn'}) 63 | .then((res) => { 64 | expect(res).to.exist; 65 | done(); 66 | }) 67 | .catch((e) => { 68 | expect(e).to.not.exist; 69 | done(); 70 | }); 71 | 72 | }); 73 | 74 | it('should accept a callback function', (done) => { 75 | /** reset counter */ 76 | count = 0; 77 | 78 | newFunc({keyword: 'Brooklyn'}, (err, res) => { 79 | expect(err).to.not.exist; 80 | expect(res).to.exist; 81 | newFunc({}, (err, res) => { 82 | expect(res).to.not.exist; 83 | expect(err).to.exist; 84 | done(); 85 | }); 86 | }); 87 | }); 88 | 89 | it('should be able to catch an error in catch block', (done) => { 90 | function errorPromise() { 91 | return Promise.reject('error on purpose'); 92 | } 93 | const errorFunc = api(errorPromise, 'Interest over time', interestHandler); 94 | 95 | errorFunc({keyword: 'Brooklyn'}) 96 | .then((e) => { 97 | expect(e).to.not.exist; 98 | done(); 99 | }) 100 | .catch((e) => { 101 | expect(e).to.exist; 102 | done(); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /test/index.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import chai from 'chai'; 3 | import google from '../src'; 4 | 5 | const expect = chai.expect; 6 | 7 | describe('index', () => { 8 | describe('should have the following methods:', () => { 9 | it('autoComplete', () => { 10 | expect(google.autoComplete).to.exist; 11 | expect(google.autoComplete).to.be.a('function'); 12 | }); 13 | 14 | it('interestByRegion', () => { 15 | expect(google.interestByRegion).to.exist; 16 | expect(google.interestByRegion).to.be.a('function'); 17 | }); 18 | 19 | it('interestOverTime', () => { 20 | expect(google.interestOverTime).to.exist; 21 | expect(google.interestOverTime).to.be.a('function'); 22 | }); 23 | 24 | it('relatedQueries', () => { 25 | expect(google.relatedQueries).to.exist; 26 | expect(google.relatedQueries).to.be.a('function'); 27 | }); 28 | 29 | it('relatedTopics', () => { 30 | expect(google.relatedTopics).to.exist; 31 | expect(google.relatedTopics).to.be.a('function'); 32 | }); 33 | 34 | it('realTimeTrends', () => { 35 | expect(google.realTimeTrends).to.exist; 36 | expect(google.realTimeTrends).to.be.a('function'); 37 | }); 38 | 39 | it('dailyTrends', () => { 40 | expect(google.dailyTrends).to.exist; 41 | expect(google.dailyTrends).to.be.a('function'); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /test/utilities.spec.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | import chai from 'chai'; 3 | import { 4 | constructInterestObj, 5 | constructTrendingObj, 6 | convertDateToString, 7 | formatResolution, 8 | formatTime, 9 | formatComparisonItems, 10 | getInterestResults, 11 | getTrendingResults, 12 | isLessThan7Days, 13 | parseResults, 14 | } from '../src/utilities'; 15 | import request from '../src/request'; 16 | 17 | const expect = chai.expect; 18 | 19 | describe('utilities', () => { 20 | 21 | describe('isLessThan7Days', () => { 22 | it('should return true if difference is less than 7 days', () => { 23 | const d1 = new Date('2017-02-04'); 24 | const d2 = new Date('2017-02-10'); 25 | const d3 = new Date('2017-02-01'); 26 | 27 | expect(isLessThan7Days(d1, d2)).to.be.true; 28 | expect(isLessThan7Days(d2, d3)).to.be.false; 29 | }); 30 | }); 31 | 32 | describe('convertDateToString', () => { 33 | it('should be able to return a date formatted as YYYY-MM-DD', () => { 34 | const d = new Date('2017-02-04'); 35 | 36 | expect(convertDateToString(d)).to.equal('2017-02-4'); 37 | }); 38 | 39 | it('should be able to return a date formatted as YYYY-MM-DDTHH\\:MM\\:SS', 40 | () => { 41 | const d = new Date('2017', '01', '04', '12', '43'); 42 | const utcHour = d.getUTCHours(); 43 | 44 | expect(convertDateToString(d, true)).to.equal( 45 | `2017-02-4T${utcHour}\\:43\\:00`); 46 | }); 47 | 48 | it('should be able to return a date formatted as YYYYMMDDTHH\\:MM\\:SS', 49 | () => { 50 | const d = new Date('2017', '01', '04', '12', '43'); 51 | const utcHour = d.getUTCHours(); 52 | 53 | expect(convertDateToString(d, true, true)).to.equal( 54 | `20170204T${utcHour}\\:43\\:00`); 55 | }); 56 | }); 57 | 58 | describe('formatTime', () => { 59 | it('should make endTime the current date if not provided', () => { 60 | const d = new Date(); 61 | const endTime = convertDateToString(d); 62 | const time = formatTime({}).time.split(' '); 63 | 64 | expect(formatTime({}).time).to.exist; 65 | expect(time[1]).to.equal(endTime); 66 | }); 67 | 68 | it('should make the startTime 2004-01-01 if not provided', () => { 69 | const time = formatTime({}).time.split(' '); 70 | 71 | expect(formatTime({}).time).to.exist; 72 | expect(time[0]).to.equal('2004-01-1'); 73 | }); 74 | 75 | it('should include time if dates are less than a week and ' + 76 | 'granularTimeResolution set to true', () => { 77 | const endTime = new Date(); 78 | const startTime = new Date(Date.now() - (5 * 24 * 60 * 60 * 1000)); 79 | const startTime2 = new Date(Date.now() - (8 * 24 * 60 * 60 * 1000)); 80 | 81 | expect(/T/.test(formatTime({ 82 | endTime, 83 | startTime, 84 | granularTimeResolution: true, 85 | }).time)).to.be.true; 86 | 87 | expect(/T/.test(formatTime({ 88 | endTime, 89 | startTime, 90 | granularTimeResolution: false, 91 | }).time)).to.be.false; 92 | 93 | expect(/T/.test(formatTime({ 94 | endTime, 95 | startTime: startTime2, 96 | granularTimeResolution: true, 97 | }).time)).to.be.false; 98 | }); 99 | 100 | it('should switch startTime and endTime if startTime is after endTime', 101 | () => { 102 | const endTime = new Date(); 103 | const startTime = new Date(Date.now() + (5 * 24 * 60 * 60 * 1000)); 104 | const result = formatTime({startTime, endTime}); 105 | 106 | expect(result.startTime).to.equal(endTime); 107 | expect(result.endTime).to.equal(startTime); 108 | }); 109 | }); 110 | 111 | describe('formatComparisonItems', () => { 112 | it('should return single comparisonItem', () => { 113 | let keywords = formatComparisonItems({ keyword: 'test' }); 114 | 115 | expect(keywords).to.deep.equal([{ keyword: 'test' }]); 116 | }); 117 | 118 | it('should return an array of comparisonItems', () => { 119 | let keywords = formatComparisonItems({ 120 | keyword: ['test', 'test2'], 121 | startDate: '2017-01-01', 122 | }); 123 | 124 | expect(keywords).to.deep.equal([ 125 | {keyword: 'test', startDate: '2017-01-01'}, 126 | {keyword: 'test2', startDate: '2017-01-01'}, 127 | ]); 128 | }); 129 | 130 | it('should return comparisonItems with same region', () => { 131 | let keywords = formatComparisonItems({ 132 | keyword: ['test', 'test2'], 133 | startDate: '2017-01-01', 134 | geo: 'GB', 135 | }); 136 | 137 | expect(keywords).to.deep.equal([ 138 | {keyword: 'test', startDate: '2017-01-01', geo: 'GB'}, 139 | {keyword: 'test2', startDate: '2017-01-01', geo: 'GB'}, 140 | ]); 141 | }); 142 | 143 | it('should return comparisonItems with different regions', () => { 144 | let keywords = formatComparisonItems({ 145 | keyword: ['test', 'test2'], 146 | startDate: '2017-01-01', 147 | geo: ['GB', 'ES'], 148 | }); 149 | 150 | expect(keywords).to.deep.equal([ 151 | {keyword: 'test', startDate: '2017-01-01', geo: 'GB'}, 152 | {keyword: 'test2', startDate: '2017-01-01', geo: 'ES'}, 153 | ]); 154 | }); 155 | 156 | it('should duplicate single keyword searches for multiple regions', () => { 157 | let keywords = formatComparisonItems({ 158 | keyword: 'test', 159 | startDate: '2018-01-01', 160 | geo: ['US-MA', 'US-VA'], 161 | }); 162 | 163 | expect(keywords).to.deep.equal([ 164 | {keyword: 'test', startDate: '2018-01-01', geo: 'US-MA'}, 165 | {keyword: 'test', startDate: '2018-01-01', geo: 'US-VA'}, 166 | ]); 167 | }); 168 | }); 169 | 170 | describe('constructInterestObj', () => { 171 | it('should return an error if first argument is not an object', () => { 172 | expect(constructInterestObj('not an obj').obj).to.be.an('error'); 173 | }); 174 | 175 | it('should return an error if keyword is not provided', () => { 176 | expect(constructInterestObj({endTime: new Date()}).obj) 177 | .to.be.an('error'); 178 | expect(constructInterestObj({keywords: 'Brooklyn'}).obj) 179 | .to.be.an('error'); 180 | }); 181 | 182 | it('should return an error if keyword and geo length are not equal', () => { 183 | expect(constructInterestObj({ 184 | keyword: ['foo', 'bar'], 185 | geo: ['Brooklyn', 'DC', 'Boston'], 186 | }).obj).to.be.an('error'); 187 | }); 188 | 189 | it('should return an error if startTime is not a date', () => { 190 | expect(constructInterestObj({ 191 | keyword: 'test', 192 | startTime: '2018-01-01', 193 | }).obj).to.be.an('error'); 194 | }); 195 | 196 | it('should return an error if endTime is not a date', () => { 197 | expect(constructInterestObj({ 198 | keyword: 'test', 199 | endTime: '2018-01-01', 200 | }).obj).to.be.an('error'); 201 | }); 202 | 203 | it('should return an error if keyword and geo length are not equal', () => { 204 | expect(constructInterestObj({ 205 | keyword: ['foo', 'bar'], 206 | geo: ['Brooklyn', 'DC', 'Boston'], 207 | }).obj).to.be.an('error'); 208 | }); 209 | 210 | it('should return an error if startTime is not a date', () => { 211 | expect(constructInterestObj({ 212 | keyword: 'test', 213 | startTime: '2018-01-01', 214 | }).obj).to.be.an('error'); 215 | }); 216 | 217 | it('should return an error if endTime is not a date', () => { 218 | expect(constructInterestObj({ 219 | keyword: 'test', 220 | endTime: '2018-01-01', 221 | }).obj).to.be.an('error'); 222 | }); 223 | 224 | it('should return an error if cbFunc is not a function', () => { 225 | expect(constructInterestObj({keyword: 'Brooklyn'}, 'str').obj) 226 | .to.be.an('error'); 227 | }); 228 | 229 | it('should not require a callback function', () => { 230 | expect(constructInterestObj({keyword: 'Brooklyn'}).obj) 231 | .to.not.be.an('error'); 232 | }); 233 | 234 | it('should create a callback if one is not provided', () => { 235 | expect(constructInterestObj({keyword: 'Brooklyn'}).cbFunc) 236 | .to.be.a('function'); 237 | }); 238 | 239 | it('should add default hl to english if not provided', () => { 240 | expect(constructInterestObj({keyword: 'Brooklyn'}).obj.hl) 241 | .to.equal('en-US'); 242 | }); 243 | 244 | it('should add default category to 0 if not provided', () => { 245 | expect(constructInterestObj({keyword: 'Brooklyn'}).obj.category) 246 | .to.equal(0); 247 | }); 248 | 249 | it('@test should have a property if provided', () => { 250 | expect(constructInterestObj({ 251 | keyword: 'Brooklyn', 252 | property: 'youtube', 253 | }).obj.property).to.equal('youtube'); 254 | }); 255 | 256 | it('@test has only allowed properties', () => { 257 | expect(constructInterestObj({ 258 | keyword: 'Brooklyn', 259 | property: [], 260 | }).obj.property).to.equal(''); 261 | expect(constructInterestObj({ 262 | keyword: 'Brooklyn', 263 | property: 'netflix', 264 | }).obj.property).to.equal(''); 265 | expect(constructInterestObj({ 266 | keyword: 'Brooklyn', 267 | property: undefined, 268 | }).obj.property).to.equal(''); 269 | }); 270 | }); 271 | 272 | describe('formatResolution', () => { 273 | const resolutions = ['COUNTRY', 'REGION', 'CITY', 'DMA']; 274 | 275 | it('should accept all words on the enumerated list', () => { 276 | const isItTrue = resolutions.every(formatResolution); 277 | 278 | expect(isItTrue).to.be.true; 279 | }); 280 | 281 | it('should return an empty string if word is not on list', () => { 282 | expect(formatResolution('random string')).to.equal(''); 283 | }); 284 | 285 | it('should capitalize a word on the list', () => { 286 | expect(formatResolution('country')).to.equal('COUNTRY'); 287 | }); 288 | }); 289 | 290 | describe('getInterestResults', () => { 291 | it('should return a function', () => { 292 | const resultsFunc = getInterestResults(); 293 | 294 | expect(resultsFunc).to.be.a('function'); 295 | }); 296 | 297 | it('should eventually return', (done) => { 298 | const resultsFunc = getInterestResults(request); 299 | const { obj } = constructInterestObj({keyword: 'Brooklyn'}); 300 | 301 | resultsFunc('Interest over time', obj) 302 | .then((res) => { 303 | expect(res).to.exist; 304 | expect(JSON.parse(res)).to.not.be.an('error'); 305 | done(); 306 | }) 307 | .catch((e) => { 308 | expect(e).to.not.exist(); 309 | done(); 310 | }); 311 | }); 312 | 313 | it('should error if widgets do not contain selected api type', (done) => { 314 | function promiseFunc() { 315 | return new Promise((resolve, reject) => { 316 | setTimeout(() => { 317 | const fakeReqObj = { 318 | widgets: [{ 319 | request: { 320 | requestOptions: {}, 321 | }, 322 | token: 'dogman', 323 | title: 'Related topics', 324 | }], 325 | }; 326 | 327 | resolve(`1234${JSON.stringify(fakeReqObj)}`); 328 | }, 500); 329 | }); 330 | } 331 | 332 | const resultsFunc = getInterestResults(promiseFunc); 333 | const { obj } = constructInterestObj({ keyword: 'Brooklyn' }); 334 | 335 | resultsFunc('Interest over time', obj) 336 | .catch((e) => { 337 | const message = 'Available widgets does not contain selected api type'; 338 | 339 | expect(e.message).to.equal(message); 340 | done(); 341 | }); 342 | }); 343 | 344 | it('should error if JSON is not valid', (done) => { 345 | let count = 0; 346 | const expectedFailureMsg = 'not valid json'; 347 | 348 | function promiseFunc() { 349 | return new Promise((resolve, reject) => { 350 | setTimeout(() => { 351 | if (count === 0) { 352 | count += 1; 353 | 354 | const fakeReqObj = { 355 | widgets: [{ 356 | request: { 357 | requestOptions: {}, 358 | }, 359 | token: 'dogman', 360 | title: 'Interest over time', 361 | }], 362 | }; 363 | 364 | resolve(`1234${JSON.stringify(fakeReqObj)}`); 365 | } else { 366 | resolve(expectedFailureMsg); 367 | } 368 | }, 500); 369 | }); 370 | } 371 | 372 | const resultsFunc = getInterestResults(promiseFunc); 373 | const { obj } = constructInterestObj({keyword: 'Brooklyn'}); 374 | 375 | resultsFunc('Interest over time', obj) 376 | .then((res) => { 377 | expect(res).to.exist; 378 | expect(res).to.equal(expectedFailureMsg); 379 | done(); 380 | }) 381 | .catch((e) => { 382 | done(); 383 | }); 384 | }); 385 | }); 386 | 387 | describe('parseResults', () => { 388 | it('should return a javascript object', () => { 389 | // The 'abcd' is the 4 characters that are returned by the request 390 | let validJSON = parseResults('abcd{' + 391 | '"some": "valid json",' + 392 | '"widgets": ["a", "b", "c"]' + 393 | '}'); 394 | 395 | expect(validJSON).to.deep.equal(['a', 'b', 'c']); 396 | }); 397 | 398 | it('should throw an error on invalid JSON', () => { 399 | expect(() => parseResults('')).to.throw(Error); 400 | }); 401 | }); 402 | 403 | describe('constructTrendingObj', () => { 404 | it('should return an error if first argument is not an object', () => { 405 | expect(constructTrendingObj('not an obj').obj).to.be.an('error'); 406 | }); 407 | 408 | it('should return an error if cbFunc is not a function', () => { 409 | expect(constructTrendingObj({geo: 'US'}, 'str').obj).to.be.an('error'); 410 | }); 411 | 412 | it('should not require a callback function', () => { 413 | expect(constructTrendingObj({geo: 'US'}).obj).to.not.be.an('error'); 414 | }); 415 | 416 | it('should create a functioning callback if one is not provided', () => { 417 | expect(constructTrendingObj({geo: 'US'}).cbFunc).to.be.a('function'); 418 | expect(constructTrendingObj({geo: 'US'}) 419 | .cbFunc(new Error())).to.be.an('error'); 420 | expect(constructTrendingObj({geo: 'US'}).cbFunc(0, '')).to.equal(''); 421 | }); 422 | 423 | it('should add default hl to english if not provided', () => { 424 | expect(constructTrendingObj({geo: 'US'}).obj.hl).to.equal('en-US'); 425 | }); 426 | 427 | it('should add default category to \'all\' if not provided', () => { 428 | expect(constructTrendingObj({geo: 'US'}).obj.category).to.equal('all'); 429 | }); 430 | 431 | it('should return an error if the geo is not provided', () => { 432 | expect(constructTrendingObj({trendDate: '2018-12-25'}).obj) 433 | .to.be.an('error'); 434 | }); 435 | 436 | it('should default trendDate to today if not provided', () => { 437 | expect( 438 | convertDateToString(constructTrendingObj( 439 | {geo: 'US', trendDate: '2018-12-25'}).obj.trendDate)).to.equal( 440 | convertDateToString(new Date())); 441 | }); 442 | 443 | it('should default trendDate to today provided in wrong format', () => { 444 | expect( 445 | convertDateToString( 446 | constructTrendingObj({geo: 'US', trendDate: '2018-12-25'}) 447 | .obj.trendDate)).to.equal(convertDateToString(new Date())); 448 | }); 449 | 450 | it('should default TimeZone to the current TZ if not provided', () => { 451 | expect(constructTrendingObj({geo: 'US'}).obj.timezone).to.equal( 452 | new Date().getTimezoneOffset()); 453 | }); 454 | 455 | it('should default ns to 15 if not not provided', () => { 456 | expect(constructTrendingObj({geo: 'US'}).obj.ns).to.equal(15); 457 | }); 458 | }); 459 | 460 | describe('getTrendingResults', () => { 461 | it('should return a function', () => { 462 | const resultsFunc = getTrendingResults(); 463 | 464 | expect(resultsFunc).to.be.a('function'); 465 | }); 466 | 467 | it('should eventually return', (done) => { 468 | const resultsFunc = getTrendingResults(request); 469 | const { obj } = constructTrendingObj({geo: 'US'}); 470 | 471 | resultsFunc('Daily trends', obj) 472 | .then((res) => { 473 | expect(res).to.exist; 474 | expect(JSON.parse(res)).to.not.be.an('error'); 475 | done(); 476 | }) 477 | .catch((e) => { 478 | expect(e).to.not.exist(); 479 | done(); 480 | }); 481 | }); 482 | 483 | it('should error if JSON is not valid', (done) => { 484 | const expectedFailureMsg = 'not valid json'; 485 | 486 | function promiseFunc() { 487 | return new Promise((resolve, reject) => { 488 | setTimeout(() => { 489 | resolve(expectedFailureMsg); 490 | }, 500); 491 | }); 492 | } 493 | 494 | const resultsFunc = getTrendingResults(promiseFunc); 495 | const { obj } = constructTrendingObj({geo: 'US'}); 496 | 497 | resultsFunc('Daily trends', obj) 498 | .then((res) => { 499 | expect(res).to.exist; 500 | expect(res).to.equal(expectedFailureMsg); 501 | done(); 502 | }) 503 | .catch((e) => { 504 | done(); 505 | }); 506 | }); 507 | }); 508 | }); 509 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require('webpack'); 2 | var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; 3 | var path = require('path'); 4 | var env = require('yargs').argv.mode; 5 | 6 | var libraryName = 'google-trends-api'; 7 | 8 | var plugins = [], outputFile; 9 | 10 | if (env === 'build') { 11 | plugins.push(new UglifyJsPlugin({ minimize: true })); 12 | outputFile = libraryName + '.min.js'; 13 | } else { 14 | outputFile = libraryName + '.js'; 15 | } 16 | 17 | var config = { 18 | entry: __dirname + '/src/index.js', 19 | devtool: 'source-map', 20 | output: { 21 | path: __dirname + '/lib', 22 | filename: outputFile, 23 | library: libraryName, 24 | libraryTarget: 'umd', 25 | umdNamedDefine: true, 26 | }, 27 | module: { 28 | loaders: [ 29 | { 30 | test: /(\.jsx|\.js)$/, 31 | loader: 'babel', 32 | exclude: /(node_modules|bower_components)/, 33 | }, 34 | { 35 | test: /(\.jsx|\.js)$/, 36 | loader: 'eslint-loader', 37 | exclude: /node_modules/, 38 | }, 39 | { test: /\.json$/, loader: 'json-loader' }, 40 | ], 41 | }, 42 | resolve: { 43 | root: path.resolve('./src'), 44 | extensions: ['', '.js'], 45 | }, 46 | plugins: plugins, 47 | target: 'node', 48 | }; 49 | 50 | module.exports = config; 51 | --------------------------------------------------------------------------------