Simple SEO forecasting

by Charlie Jackson

Updated on October 8th, 2022 at 12:00 PM

weighted average rank in pandas

If you're in the world of SEO, you’ve likely seen the graph above before - it's from SEMrush and shows the estimated organic traffic for this domain ( It's worth pointing out here that there are many other tools that offer this information, I've just chosen SEMrush as it is one of the more popular ones. You can input any domain you want and SEMrush gives you the organic traffic. This organic traffic number should be taken with a pinch of salt - it's an estimation of what SEMrush believe the domain receives from organic traffic. But how does it work?

Visibility tools - how do they work?

SEMrush has a large keyword database of searches made in Google and other search engines. They also track how many searches a particular keyword receives and they track what domains are ranking. So, for example, the keyword ‘football’ gets searched 1.2 million times per month (on average across a 12 month period). The BBC ranks in position 1 here, so SEMrush will estimate that perhaps 20% of those 1.2 million searches will go to the BBC on a monthly basis - that is 240,000 clicks just from the term ‘football’. When SEMrush combine and sum all the keywords that the BBC ranks for (based upon their keyword database) they get an estimate of what the BBC receives on a monthly basis.

Estimating clicks - a simple function

In the SEO world we often need to estimate organic traffic for a given keyword set for forecasting, for example if we can target a new segment of keywords or improve a ranking position of a keyword, how many clicks can we expect to recieve? Estimating clicks is a simple function monthly search volume for a keyword, the ranking position of a URL and an estimated click through rate.

Below I have provided some industry average click through rates for different positions in search engines result pages within a Python dictionary. The function accepts search volume and a position for ranking keyword and applies a CTR based upon the position to return the estimated number of clicks from the given search term.

ctr_dct = {1 : 0.18000,2 : 0.09000,3 : 0.07600,4 : 0.06000,5 : 0.05500,6 : 0.05000,7 : 0.03000,8 : 0.02250,9 : 0.01500,10 : 0.01000,11 : 0.00850,12 : 0.00800,13 : 0.00750,14 : 0.00700,15 : 0.00650,16 : 0.00600,17 : 0.00550,18 : 0.00500,19 : 0.0050,20 : 0.00450,21 : 0.00385,22 : 0.00370,23 : 0.00355,24 : 0.0030,25 : 0.00325,26 : 0.00310,27 : 0.00295,28 : 0.00280,29 : 0.00265,30 : 0.00200,31 : 0.00190,32 : 0.00180,33 : 0.00170,34 : 0.00160,35 : 0.00150,36 : 0.0010,37 : 0.00130,38 : 0.00120,39 : 0.00110,40 : 0.00100,41 : 0.00090,42 : 0.00080,43 : 0.00070,44 : 0.00060,45 : 0.00050,46 : 0.00040,47 : 0.00030,48 : 0.00020,  49 : 0.00010,50 : 0.00000}

def estimted_clicks(position, sv):
  # pass in a postion for search volume for a keyword
  sv       = int(sv)
  position = int(position)

  if position in ctr_dct:
    return ctr_dct[position] * sv
  return 0

Passing a position and search volume into my function returns an estimated number of clicks. For example, the keyword 'seo visibility' gets 170 searches per month - in the unlikely event this blog posts ranks in position 1 for this keyword I could expect recieve 31 clicks per month. This is of course is a very rough guess - the CTR is likely to be different to my estimated 18% and the post may rank for other keywords.

estimted_clicks(1, 170)
# returns 30.59


Stakeholders will nearly always ask what the return on investment will be from producing content and this is perhaps the most likely reason you need to do forecasting. SEO forecasting is exceptionally challenging with a huge number of variables, and simply showing the number of clicks an article could produce in a best guess position is often the best way to get buy in.