Finding SEO opportunities through rising trends & Node.js

Nacho Mascort
Softonic Engineering
5 min readApr 1, 2020

--

These last months we’ve seen how programming has gained a lot of followers in the SEO world and one of the reasons why it happened is for the ability to scale & automate processes.

SEO has evolved.

Let me exemplify this last phrase with this post’s topic: rising trends.

Google Trends

Google Trends is a useful tool that every SEO professional use to stay ahead of its competitors to rank first for hot topics that bring huge amounts of traffic. One of the best modules of Trends is the ‘Related queries’ section, filtered by ‘Rising’.

The ‘Related queries’ module returns a list of hot topics that are growing fast based on a seed keyword, the keyword that we search for in the first place in the tool.

Rising trends for the seed keyword: demo

Capcom, the video-game company, released Resident Evil 3's (re3) demo last week and if we search for the trends of ‘demo’ for the last 7 days (written in march 26th) we’ll see that the game is in that list as a very hot topic at the moment.

It seems like this module works.

So, if we were a small site we can take a specific list of seed keywords and extract all the hot topics that we want to rank and create content according to those topics.

What happens when you are working on a site like Softonic with hundreds of thousands programs in different verticals, platforms and with a worldwide audience?

Programming comes into play.

In this post I want to share one of the many scripts we use on a daily basis to scale our SEO process.

Rising trendy queries - The script

Let me start from the end, the final output that we’ll receive when the script runs:

  • Raw: The raw information with 4 columns: query, value(% of increase), country & seed keyword
  • By country: The queries grouped by country in order to find the ones more repeated across the world
Output of the rising trends script

We could add more groups but the one that provides the count by country is the one that reflects the real growth of a topic.

Structure

The structure of the app is as follows:

.
├── Dockerfile
├── Jenkinsfile
├── config
│ └── seedKeywords.json
├── docker-compose.yaml
├── index.js
├── libs
│ ├── csv.js
│ └── serpwow.js
├── output
│ ├── rising-trends-by-country.csv
│ └── rising-trends-raw.csv
├── package.json
└── yarn.lock

In this post I will explain the core functionality of the app, so the files that I will explain are:

  • config folder/file
  • libs folder
  • index.js

The rest of files are for automating the entire process in order to upload the files every day in a Slack channel.

The notification that the team receives on a daily basis

If the post gets a decent amount of claps it will have a second part explaining how to automate all this process.

Config folder

In the config there’s a JSON file with the relationship between seed keywords & countries.

Something like this:

An example JSON config file

The JSON contains two main properties:

  • Site: The main site related to that seed of keywords
  • Seed groups: An array of objects with one property “target language” with two nested properties: seed keywords & countries

All this information it’s necessary to filter for the correct values in our main() function when we call the API that will get us the data we seek.

Libs folder

In this folder there are the files with the functions related to requesting the SerpWow API (great tool btw)and the helpers to write in CSV format (with the logic that we want in the CSV files).

We create 4 CSV functions:

  • createCSV()
  • removeCurrentCSV()
  • addRaw()
  • addByCountry()

I won’t get into the details of the CSV functions because the output can vary for every situation/team/company, maybe you want to apply the data into Data Studio or in a database so I’m just listing the function as complementary info to show our approach.

In order to use the SerpWow API in NodeJS & extract the info of that module we need to:

// Import the library
const SerpWow = require('google-search-results-serpwow');
// Create an instance of the SerpWow object
let serpwow = new SerpWow('YOUR_API_KEY_HERE');
// Do the request with specific with your params
const params = {
q,
search_type: 'trends',
no_cache: 'true',
trends_geo: geo,
trends_type: 'web',
time_period: 'last_week'
};
// retrieve the search results as JSON
const results = await serpwow.json(params);
//extract every rising query
const rising_queries = results.related_queries.map(result => result.queries);

I supposed that you saw the await keyword in that code, we made every request to the API inside an Async function (otherwise an error would have appeared)and then we return an object with the info that we wanted.

Something like this:

async function getRisingTrends(queries, geo) {
// Your request(s) to the API
}
// Export that function
module.exports = {
getRisingTrends
}

More info regarding Async/Await.

Index.js

Finally, where the magic happens.

We can divide the index.js file into three parts:

  • The imports
  • main() function
  • init() function

I want to show you all of three but focusing on the main() function.

First, we need to import all the required functions:

const serpwow = require('./libs/serpwow.js');
const seedKeywords = require('./config/seedKeywords.json');
const csv = require('./libs/csv.js');

No big magic above, just importing all what we’ve defined previously.

Then, it’s time for the main() function

async function main(queries, countries) {  // Create a new CSV where to store the output values
csv.newCSV();
// For every language we iterate and wait
// to resolve an array of Promises
const risingTrendsbyCountries =
await Promise.all(countries.map(async country => {
...
// Get Rising Trends of a group of queries for a given country
// and add it to the CSV
csv.addRaw(serpwow.getRisingTrends(queries, country));
...
return risingTrends;
}));
// return the final object with all info
// in order to create the countries group into the CSV
return risingTrendsByCountries.flat();
}

The main function has been slightly modified to show its core functionality, if you want to try this code you will need to tweak the code (or it will break) in order to make it work with your configs

Finally, we have the init() function that as its own name indicates it will start the app and it will make the final count in order to add the countries SUM into the CSV.

That’s all folks! I hope that you enjoyed the post and that you’ll find it useful.

Remember, for the second part explaining how we automate all this process clap a lot to this content.

Thanks for reading!

--

--