semrush 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +88 -0
- data/Rakefile +27 -0
- data/lib/semrush.rb +38 -0
- data/lib/semrush/exception.rb +11 -0
- data/lib/semrush/exception/api_access_disabled.rb +7 -0
- data/lib/semrush/exception/bad_api_key.rb +7 -0
- data/lib/semrush/exception/bad_argument.rb +11 -0
- data/lib/semrush/exception/bad_query.rb +7 -0
- data/lib/semrush/exception/nothing_found.rb +7 -0
- data/lib/semrush/exception/unknown_error.rb +7 -0
- data/lib/semrush/report.rb +298 -0
- data/lib/semrush/version.rb +3 -0
- data/lib/tasks/semrush_tasks.rake +4 -0
- metadata +100 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2011 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
= Semrush
|
2
|
+
|
3
|
+
Semrush is a ruby wrapper for the SEMRush API.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
Add the gem to your Gemfile:
|
8
|
+
|
9
|
+
gem install semrush
|
10
|
+
|
11
|
+
Create an initializer, for instance semrush.rb with the following:
|
12
|
+
|
13
|
+
Semrush.config do |config|
|
14
|
+
config.api_key = "7899esf6874"
|
15
|
+
end
|
16
|
+
|
17
|
+
Replace '7899esf6874' with your SEMRush api key.
|
18
|
+
|
19
|
+
== Getting started
|
20
|
+
|
21
|
+
First, create a report for a domain, a URL or a phrase with:
|
22
|
+
|
23
|
+
report = Semrush::Report.domain("seobook.com") # for the "seobook.com" domain
|
24
|
+
report = Semrush::Report.url("http://tools.seobook.com/") # for the "http://tools.seobook.com/" url
|
25
|
+
report = Semrush::Report.phrase("search+engine+optimization") # for the "search+engine+optimization" phrase
|
26
|
+
|
27
|
+
Then run the report type you need:
|
28
|
+
|
29
|
+
basic_data = report.basics
|
30
|
+
|
31
|
+
or
|
32
|
+
|
33
|
+
keywords_data = report.keywords_organic
|
34
|
+
|
35
|
+
== Parameters
|
36
|
+
|
37
|
+
You may use the following parameters:
|
38
|
+
|
39
|
+
:db # (String) select the google engine ('us' for google.comn 'fr' for google.fr)
|
40
|
+
:api_key # (String) change the api_key
|
41
|
+
:limit # (Integer) select only the first 'limit' entries
|
42
|
+
:offset # (Integer) skip the first 'offset' entries
|
43
|
+
:export_columns # (String) select the columns you want to fetch, for instance: :export_columns => "Dn,Rk"
|
44
|
+
|
45
|
+
Some examples:
|
46
|
+
|
47
|
+
report = Semrush::Report.domain("seobook.com", :db => 'us', :limit => 100)
|
48
|
+
data = report.basics
|
49
|
+
|
50
|
+
or
|
51
|
+
|
52
|
+
report = Semrush::Report.domain("seobook.com")
|
53
|
+
data = report.basics(:db => 'us', :limit => 100)
|
54
|
+
|
55
|
+
You will find more information about these parameters at http://www.semrush.com/api.html
|
56
|
+
|
57
|
+
== Reports
|
58
|
+
|
59
|
+
=== Source of reports
|
60
|
+
|
61
|
+
They are 3 sources for the reports: domain, url and phrase.
|
62
|
+
|
63
|
+
report = Semrush::Report.domain("seobook.com") # for the "seobook.com" domain
|
64
|
+
report = Semrush::Report.url("http://tools.seobook.com/") # for the "http://tools.seobook.com/" url
|
65
|
+
report = Semrush::Report.phrase("search+engine+optimization") # for the "search+engine+optimization" phrase
|
66
|
+
|
67
|
+
=== Report types
|
68
|
+
|
69
|
+
You may call for one of the following report types:
|
70
|
+
|
71
|
+
data = report.basics # main report for either a domain or a phrase
|
72
|
+
data = report.keywords_organic # keywords organic report for either a domain or a URL
|
73
|
+
data = report.keywords_adwords # keywords adwords report for either a domain or a URL
|
74
|
+
data = report.competitors_organic # for a domain
|
75
|
+
data = report.competitors_adwords # for a domain
|
76
|
+
data = report.competitors_organic_by_adwords # for a domain
|
77
|
+
data = report.competitors_adwords_by_organic # for a domain
|
78
|
+
data = report.related # keywords related report for a phrase
|
79
|
+
|
80
|
+
For more information about the report types, please read http://www.semrush.com/api.html
|
81
|
+
|
82
|
+
== About authors
|
83
|
+
|
84
|
+
This gem is inspired by the work of Cramer Development for the semrush-client plugin (https://github.com/cramerdev/semrush-client).
|
85
|
+
|
86
|
+
It has been rewritten and gemified for the internal use in Weboglobin (http://fr.weboglobin.com).
|
87
|
+
|
88
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rdoc/task'
|
5
|
+
rescue LoadError
|
6
|
+
require 'rdoc/rdoc'
|
7
|
+
require 'rake/rdoctask'
|
8
|
+
RDoc::Task = Rake::RDocTask
|
9
|
+
end
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = 'rdoc'
|
13
|
+
rdoc.title = 'Semrush'
|
14
|
+
rdoc.options << '--line-numbers'
|
15
|
+
rdoc.rdoc_files.include('README.rdoc')
|
16
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
17
|
+
end
|
18
|
+
|
19
|
+
require "rspec/core/rake_task"
|
20
|
+
|
21
|
+
desc "Run all test with spec"
|
22
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
23
|
+
t.rspec_opts = %w[--color]
|
24
|
+
t.pattern = 'spec/*_spec.rb'
|
25
|
+
end
|
26
|
+
desc "Run tests"
|
27
|
+
task :default => :spec
|
data/lib/semrush.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'csv'
|
4
|
+
require 'rubygems'
|
5
|
+
require 'active_support/all'
|
6
|
+
require 'pony' #for the warning mails
|
7
|
+
require 'semrush/exception'
|
8
|
+
require 'semrush/report'
|
9
|
+
|
10
|
+
module Semrush
|
11
|
+
API_REPORT_URL = "http://%DB%.api.semrush.com/?action=report&type=%REPORT_TYPE%&%REQUEST_TYPE%=%REQUEST%&key=%API_KEY%&display_limit=%LIMIT%&display_offset=%OFFSET%&export=api&export_columns=%EXPORT_COLUMNS%"
|
12
|
+
|
13
|
+
mattr_accessor :api_key
|
14
|
+
@@api_key = ""
|
15
|
+
mattr_accessor :debug
|
16
|
+
@@debug = false
|
17
|
+
|
18
|
+
|
19
|
+
# Email Options (TODO: remove if unnecessary)
|
20
|
+
# config.email : recipient for the email notifications (default: nil)
|
21
|
+
# config.email_options : Hash with email config (smtp, sendmail, ...). We use the Pony gem to send mails, this hash will be send to Pony.options
|
22
|
+
# config.seconds_between_mails : Minimum time (in seconds) between 2 mails with the same subject
|
23
|
+
mattr_accessor :email
|
24
|
+
mattr_accessor :email_options
|
25
|
+
@@email_options = {}
|
26
|
+
mattr_accessor :seconds_between_mails
|
27
|
+
@@seconds_between_mails = 600
|
28
|
+
mattr_accessor :too_many_queries
|
29
|
+
@@too_many_queries = {:subject => 'SemRush API: too many queries for the day', :body => 'You made too many requests for today. You should upgrade your plan in order to be able to send more requests to SemRush.'}
|
30
|
+
mattr_accessor :too_many_queries_sent_at
|
31
|
+
|
32
|
+
def self.config
|
33
|
+
yield self
|
34
|
+
Pony.options = @@email_options
|
35
|
+
raise Exception::BadApiKey.new if @@api_key.nil? || @@api_key.empty?
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Semrush
|
2
|
+
module Exception
|
3
|
+
class Base < ::Exception
|
4
|
+
def initialize query = nil, message = ""
|
5
|
+
message = "[query=#{query.inspect}] #{message}" if !query.nil?
|
6
|
+
super(message)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
Dir[File.expand_path('../exception/', __FILE__)+'/*.rb'].each {|file| require(file) }
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module Semrush
|
2
|
+
module Exception
|
3
|
+
class BadArgument < Base
|
4
|
+
|
5
|
+
end
|
6
|
+
class MandatoryParameterDomainNotSetOrEmtpy < BadArgument; end
|
7
|
+
class MandatoryParameterUrlNotSetOrEmtpy < BadArgument; end
|
8
|
+
class MandatoryParameterPhraseNotSetOrEmtpy < BadArgument; end
|
9
|
+
class WrongFormatOrEmptyKey < BadArgument; end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
module Semrush
|
2
|
+
# =Report Class
|
3
|
+
# Most of these methods take a hash parameter that may contain the following keys :
|
4
|
+
# * :db (ex: :db => "us")
|
5
|
+
# * :api_key (ex: :api_key => 'gt97s6d4a6w')
|
6
|
+
# * :limit (ex: :limit => 2000)
|
7
|
+
# * :offset (ex: :offset => 5)
|
8
|
+
# * :export_columns (ex: :export_columns => "Dn,Rk")
|
9
|
+
class Report
|
10
|
+
DBS = [:us, :uk, :ru, :de, :fr, :es, :it, :br, :au] #"us" - for Google.com, "uk" - for Google.co.uk, "ru" - for Google.ru, "de" for Google.de, "fr" for Google.fr, "es" for Google.es, "it" for Google.it Beta, "br" for Google.com.br Beta, "au" for Google.com.au Beta.
|
11
|
+
REPORT_TYPES = [:domain_rank, :domain_organic, :domain_adwords, :domain_organic_organic, :domain_adwords_adwords, :domain_organic_adwords, :domain_adwords_organic,
|
12
|
+
:phrase_this, :phrase_related,
|
13
|
+
:url_organic, :url_adwords]
|
14
|
+
REQUEST_TYPES = [:domain, :phrase, :url]
|
15
|
+
|
16
|
+
|
17
|
+
# Tries to make the api call for the report called as method (see samples on http://www.semrush.com/api.html).
|
18
|
+
# Allows calls like:
|
19
|
+
# * Semrush::Report.new.domain_rank(:request_type => :domain, :request => 'thedomain.com')
|
20
|
+
# * Semrush::Report.new.domain_organic_organic(:request_type => :domain, :request => 'thedomain.com')
|
21
|
+
# * Semrush::Report.new.phrase_related(:request_type => :phrase, :request => 'the phrase')
|
22
|
+
def method_missing(method, *args)
|
23
|
+
return super unless REPORT_TYPES.include?(method) && args.first.is_a?(Hash)
|
24
|
+
request args.first.merge(:report_type => method)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize params = {}
|
28
|
+
@parameters = params
|
29
|
+
end
|
30
|
+
|
31
|
+
# Initializes a report for a specific domain.
|
32
|
+
# Takes a hash parameter that may contain the following keys :
|
33
|
+
# * :db (ex: :db => "us")
|
34
|
+
# * :api_key (ex: :api_key => 'gt97s6d4a6w')
|
35
|
+
# * :limit (ex: :limit => "")
|
36
|
+
# * :offset (ex: :offset => "")
|
37
|
+
# * :export_columns (ex: :export_columns => "")
|
38
|
+
def self.domain domain, params = {}
|
39
|
+
self.new(params.merge(:request_type => :domain, :request => domain))
|
40
|
+
end
|
41
|
+
# Initializes a report for a specific phrase (or keyword).
|
42
|
+
# Takes a hash parameter that may contain the following keys :
|
43
|
+
# * :db (ex: :db => "us")
|
44
|
+
# * :api_key (ex: :api_key => 'gt97s6d4a6w')
|
45
|
+
# * :limit (ex: :limit => "")
|
46
|
+
# * :offset (ex: :offset => "")
|
47
|
+
# * :export_columns (ex: :export_columns => "")
|
48
|
+
def self.phrase phrase, params = {}
|
49
|
+
self.new(params.merge(:request_type => :phrase, :request => phrase))
|
50
|
+
end
|
51
|
+
# Initializes a report for a specific domain.
|
52
|
+
# Takes a hash parameter that may contain the following keys :
|
53
|
+
# * :db (ex: :db => "us")
|
54
|
+
# * :api_key (ex: :api_key => 'gt97s6d4a6w')
|
55
|
+
# * :limit (ex: :limit => "")
|
56
|
+
# * :offset (ex: :offset => "")
|
57
|
+
# * :export_columns (ex: :export_columns => "")
|
58
|
+
def self.url url, params = {}
|
59
|
+
self.new(params.merge(:request_type => :url, :request => url))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Main report.
|
63
|
+
# Available for a phrase or a domain.
|
64
|
+
# Default columns for a domain:
|
65
|
+
# * Dn - A site name.
|
66
|
+
# * Rk - Rating of sites by the number of visitors coming from the first 20 Google search results
|
67
|
+
# * Or - Keywords that this site has in TOP20 Google Organic results
|
68
|
+
# * Ot - Estimated number of visitors coming from the first 20 Google search results (per month)
|
69
|
+
# * Oc - Estimated cost of purchasing the same number of visitors
|
70
|
+
# * Ad - Keywords that this site has in TOP20 Google AdWords
|
71
|
+
# * At - Estimated number of visitors coming from AdWords (per month)
|
72
|
+
# * Ac - Estimated expenses of the site for the advertising in AdWords (per month)
|
73
|
+
# Default columns for a phrase:
|
74
|
+
# * Ph - The search query which the site has within the first 20 Google search results
|
75
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
76
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
77
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
78
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
79
|
+
def basics params = {}
|
80
|
+
domain? ? request(params.merge(:report_type => :domain_rank)) : request(params.merge(:report_type => :phrase_this))
|
81
|
+
end
|
82
|
+
|
83
|
+
# Organic Keywords report
|
84
|
+
# Can be called for a domain or a URL.
|
85
|
+
# Default columns for a domain:
|
86
|
+
# * Ph - The search query which the site has within the first 20 Google search results
|
87
|
+
# * Po - The position of the site for the search query in Google, at the moment of data collection
|
88
|
+
# * Pp - The position of the site for the search query in Google, for the previous data collection
|
89
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
90
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
91
|
+
# * Ur - URL of a page of the site which is displayed in search results for this query (landing page)
|
92
|
+
# * Tr - The ratio of the number of visitors coming to the site from this search request to all visitors coming from Google search results
|
93
|
+
# * Tc - The ratio of the estimated cost of buying the same number of visitors for this search query to the estimated cost of purchasing the same number of targeted visitors coming to this site from Google search results
|
94
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
95
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
96
|
+
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
|
97
|
+
# Default columns for a URL:
|
98
|
+
# * Ph - Search query that the URL has within the first 20 Google Organic or AdWords results
|
99
|
+
# * Po - The position of this URL for this keyword in Organic or AdWords results
|
100
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
101
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
102
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
103
|
+
# * Tr - The ratio of the number of visitors coming to the URL from this keyword to all visitors coming
|
104
|
+
# * Tc - The ratio of the estimated cost of buying the same number of visitors for this search query to the estimated cost of purchasing the same number of targeted visitors coming to this URL
|
105
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
106
|
+
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
|
107
|
+
def keywords_organic params = {}
|
108
|
+
url? ? request(params.merge(:report_type => :url_organic)) : request(params.merge(:report_type => :domain_organic))
|
109
|
+
end
|
110
|
+
|
111
|
+
# AdWords keywords report
|
112
|
+
# Can be called for a domain or a URL.
|
113
|
+
# Default columns for a domain:
|
114
|
+
# * Ph - Search query which the site buys in AdWords in Google
|
115
|
+
# * Po - The position of the ad at the time of data collection
|
116
|
+
# * Pp - The position of the ad at the time of previous data collection
|
117
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
118
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
119
|
+
# * Vu - Display URL. This is the URL displayed on your ad to identify your site to users.
|
120
|
+
# * Tr - The ratio of the number of visitors coming to the site from this ad to all visitors coming from Google AdWords
|
121
|
+
# * Tc - The ratio of site's expenditures on this particular ad to it's expenditures on all AdWords ads in general
|
122
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
123
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
124
|
+
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
|
125
|
+
# * Ur - The destination URL is the exact URL within your website that you want to send users to from your ad.
|
126
|
+
# Default columns for a URL:
|
127
|
+
# * Ph - Search query that the URL has within the first 20 Google Organic or AdWords results
|
128
|
+
# * Po - The position of this URL for this keyword in Organic or AdWords results
|
129
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
130
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
131
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
132
|
+
# * Tr - The ratio of the number of visitors coming to the URL from this keyword to all visitors coming
|
133
|
+
# * Tc - The ratio of the estimated cost of buying the same number of visitors for this search query to the estimated cost of purchasing the same number of targeted visitors coming to this URL
|
134
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
135
|
+
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
|
136
|
+
def keywords_adwords params = {}
|
137
|
+
url? ? request(params.merge(:report_type => :url_adwords)) : request(params.merge(:report_type => :domain_adwords))
|
138
|
+
end
|
139
|
+
|
140
|
+
# Competitors in organic search report
|
141
|
+
# Default columns:
|
142
|
+
# * Dn - Sites competing with this site in Google search results, sorted by the number of common keywords
|
143
|
+
# * Np - The number of keywords on which the site is displayed in search results next to the analyzed site
|
144
|
+
# * Or - Keywords that this site has in TOP20 Google Organic results
|
145
|
+
# * Ot - Estimated number of visitors coming from the first 20 Google search results (per month)
|
146
|
+
# * Oc - Estimated cost of purchasing the same number of visitors
|
147
|
+
# * Ad - Keywords that this site has in TOP20 Google AdWords
|
148
|
+
def competitors_organic params = {}
|
149
|
+
request(params.merge(:report_type => :domain_organic_organic))
|
150
|
+
end
|
151
|
+
|
152
|
+
# Competitors in AdWords search report
|
153
|
+
# Default columns:
|
154
|
+
# * Dn - Sites competing with this site in AdWords, sorted by the number of common keywords
|
155
|
+
# * Np - Number of common keywords in AdWords that these two sites buy
|
156
|
+
# * Ad - Keywords that this site has in TOP20 Google AdWords
|
157
|
+
# * At - Estimated number of visitors coming from AdWords (per month)
|
158
|
+
# * Ac - Estimated expenses of the site for the advertising in AdWords (per month)
|
159
|
+
# * Or - Keywords that this site has in TOP20 Google Organic results
|
160
|
+
def competitors_adwords params = {}
|
161
|
+
request(params.merge(:report_type => :domain_adwords_adwords))
|
162
|
+
end
|
163
|
+
|
164
|
+
# Potential ad/traffic buyers report
|
165
|
+
# Default columns:
|
166
|
+
# * Dn - The list of sites that buys ads in AdWords for those keywords that the domain under analyzis has within Google TOP20
|
167
|
+
# * Np - Number of keywords on which ads of this particular site appear and the analyzed site gets within Google TOP20
|
168
|
+
# * Ad - Keywords that this site has in TOP20 Google AdWords
|
169
|
+
# * At - Estimated number of visitors coming from AdWords (per month)
|
170
|
+
# * Ac - Estimated expenses of the site for the advertising in AdWords (per month)
|
171
|
+
# * Or - Keywords that this site has in TOP20 Google Organic results
|
172
|
+
def competitors_organic_by_adwords params = {}
|
173
|
+
request(params.merge(:report_type => :domain_organic_adwords))
|
174
|
+
end
|
175
|
+
|
176
|
+
# Potential ad/traffic sellers report
|
177
|
+
# Default columns:
|
178
|
+
# * Dn - Sites that get into Google TOP20 for keyword queries that analyzed site buy in AdWords
|
179
|
+
# * Np - The number of keywords which this site has in search results next to the AdWords ads of the analyzed site
|
180
|
+
# * Or - Keywords that this site has in TOP20 Google Organic results
|
181
|
+
# * Ot - Estimated number of visitors coming from the first 20 Google search results (per month)
|
182
|
+
# * Oc - Estimated cost of purchasing the same number of visitors
|
183
|
+
# * Ad - Keywords that this site has in TOP20 Google AdWords
|
184
|
+
def competitors_adwords_by_organic params = {}
|
185
|
+
request(params.merge(:report_type => :domain_adwords_organic))
|
186
|
+
end
|
187
|
+
|
188
|
+
# Related keyword report
|
189
|
+
# Default columns:
|
190
|
+
# * Ph - The search query which the site has within the first 20 Google search results
|
191
|
+
# * Nq - Average number of queries of this keyword in a month, for the corresponding local version of Google
|
192
|
+
# * Cp - Average price of a click on the AdWords ad for this search query, in U.S. dollars
|
193
|
+
# * Co - Competition of advertisers in AdWords for that term, the higher is the number - the higher is the competition
|
194
|
+
# * Nr - The number of search results - how many pages does Google know for this query
|
195
|
+
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
|
196
|
+
def related params = {}
|
197
|
+
request(params.merge(:report_type => :phrase_related))
|
198
|
+
end
|
199
|
+
|
200
|
+
private
|
201
|
+
|
202
|
+
def request params = {}
|
203
|
+
validate_parameters params
|
204
|
+
temp_url = "#{API_REPORT_URL}" #do not copy the constant as is or else the constant would be modified !!
|
205
|
+
@parameters.each {|k, v|
|
206
|
+
if v.blank?
|
207
|
+
temp_url.gsub!(/&[^&=]+=%#{k.to_s}%/i, '')
|
208
|
+
else
|
209
|
+
temp_url.gsub!("%#{k.to_s.upcase}%", URI.escape(v.to_s))
|
210
|
+
end
|
211
|
+
}
|
212
|
+
puts "[Semrush query] URL: #{temp_url}" if Semrush.debug
|
213
|
+
url = URI.parse(temp_url)
|
214
|
+
response = Net::HTTP.start(url.host, url.port) {|http|
|
215
|
+
http.get(url.path+"?"+url.query)
|
216
|
+
}.body rescue "ERROR :: RESPONSE ERROR (-1)" # Make this error up
|
217
|
+
response.starts_with?("ERROR") ? error(response) : parse(response)
|
218
|
+
end
|
219
|
+
|
220
|
+
# All parameters:
|
221
|
+
# * db - requested database
|
222
|
+
# * report_type - type of the report
|
223
|
+
# * api_key - user identification key, you can find it in your profile on the Semrush site
|
224
|
+
# * request_type - type of the request.
|
225
|
+
# * request - your request
|
226
|
+
# * limit - number of results returned
|
227
|
+
# * offset - says to skip that many results before beginning to return results to you
|
228
|
+
# * export_columns - list of column names, separated by coma. You may list just the column names you need in an order you need.
|
229
|
+
#
|
230
|
+
# more details in http://www.semrush.com/api.html
|
231
|
+
def validate_parameters params = {}
|
232
|
+
params.symbolize_keys!
|
233
|
+
params.delete(:db) unless DBS.include?(params[:db].try(:to_sym))
|
234
|
+
params.delete(:report_type) unless REPORT_TYPES.include?(params[:report_type].try(:to_sym))
|
235
|
+
params.delete(:request_type) unless REQUEST_TYPES.include?(params[:request_type].try(:to_sym))
|
236
|
+
@parameters = {:db => "us", :api_key => Semrush.api_key, :limit => "", :offset => "", :export_columns => ""}.merge(@parameters).merge(params)
|
237
|
+
raise Semrush::Exception::BadArgument.new(self, "Request parameter is missing: Domain name, URL, or keywords are required.") unless @parameters[:request].present?
|
238
|
+
raise Semrush::Exception::BadArgument.new(self, "Bad db: #{@parameters[:db]}") unless DBS.include?(@parameters[:db].try(:to_sym))
|
239
|
+
raise Semrush::Exception::BadArgument.new(self, "Bad report type: #{@parameters[:report_type]}") unless REPORT_TYPES.include?(@parameters[:report_type].try(:to_sym))
|
240
|
+
raise Semrush::Exception::BadArgument.new(self, "Bad request type: #{@parameters[:request_type]}") unless REQUEST_TYPES.include?(@parameters[:request_type].try(:to_sym))
|
241
|
+
end
|
242
|
+
|
243
|
+
# Format and raise an error
|
244
|
+
def error(text = "")
|
245
|
+
e = /ERROR\s(\d+)\s::\s(.*)/.match(text) || {}
|
246
|
+
name = (e[2] || "UnknownError").titleize
|
247
|
+
code = e[1] || -1
|
248
|
+
error_class = name.gsub(/\s/, "")
|
249
|
+
|
250
|
+
if error_class == "NothingFound"
|
251
|
+
[]
|
252
|
+
else
|
253
|
+
raise Semrush::Exception.const_get(error_class).new(self, "#{name} (#{code})")
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
def parse(text = "")
|
258
|
+
csv = CSV.parse(text.to_s, :col_sep => ";")
|
259
|
+
data = {}
|
260
|
+
format_key = lambda do |k|
|
261
|
+
r = {
|
262
|
+
/\s/ => "_",
|
263
|
+
/[|\.|\)|\(]/ => "",
|
264
|
+
/%/ => "percent",
|
265
|
+
/\*/ => "times"
|
266
|
+
}
|
267
|
+
k = k.to_s.downcase
|
268
|
+
r.each_pair {|pattern, replace| k.gsub!(pattern, replace) }
|
269
|
+
k.to_sym
|
270
|
+
end
|
271
|
+
|
272
|
+
# (thanks http://snippets.dzone.com/posts/show/3899)
|
273
|
+
keys = csv.shift.map(&format_key)
|
274
|
+
string_data = csv.map {|row| row.map {|cell| cell.to_s } }
|
275
|
+
string_data.map {|row| Hash[*keys.zip(row).flatten] }
|
276
|
+
rescue CSV::MalformedCSVError => csvife
|
277
|
+
tries ||= 0
|
278
|
+
if (tries += 1) < 3
|
279
|
+
retry
|
280
|
+
else
|
281
|
+
raise CSV::MalformedCSVError.new("Bad format for CSV: #{text.inspect}").tap{|e|
|
282
|
+
e.set_backtrace(csvife.backtrace)}
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def domain?
|
287
|
+
@parameters[:request_type].present? && REQUEST_TYPES.include?(@parameters[:request_type].to_sym) && @parameters[:request_type].to_sym==:domain
|
288
|
+
end
|
289
|
+
def url?
|
290
|
+
@parameters[:request_type].present? && REQUEST_TYPES.include?(@parameters[:request_type].to_sym) && @parameters[:request_type].to_sym==:url
|
291
|
+
end
|
292
|
+
def phrase?
|
293
|
+
@parameters[:request_type].present? && REQUEST_TYPES.include?(@parameters[:request_type].to_sym) && @parameters[:request_type].to_sym==:phrase
|
294
|
+
end
|
295
|
+
|
296
|
+
|
297
|
+
end
|
298
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: semrush
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 3.0.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- arambert
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-10-21 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activesupport
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 3.1.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: pony
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.0.0
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.0.0
|
46
|
+
type: :development
|
47
|
+
version_requirements: *id003
|
48
|
+
description:
|
49
|
+
email:
|
50
|
+
- arambert@weboglobin.com
|
51
|
+
executables: []
|
52
|
+
|
53
|
+
extensions: []
|
54
|
+
|
55
|
+
extra_rdoc_files: []
|
56
|
+
|
57
|
+
files:
|
58
|
+
- lib/semrush/exception/api_access_disabled.rb
|
59
|
+
- lib/semrush/exception/bad_api_key.rb
|
60
|
+
- lib/semrush/exception/bad_argument.rb
|
61
|
+
- lib/semrush/exception/bad_query.rb
|
62
|
+
- lib/semrush/exception/nothing_found.rb
|
63
|
+
- lib/semrush/exception/unknown_error.rb
|
64
|
+
- lib/semrush/exception.rb
|
65
|
+
- lib/semrush/report.rb
|
66
|
+
- lib/semrush/version.rb
|
67
|
+
- lib/semrush.rb
|
68
|
+
- lib/tasks/semrush_tasks.rake
|
69
|
+
- MIT-LICENSE
|
70
|
+
- Rakefile
|
71
|
+
- README.rdoc
|
72
|
+
homepage: http://www.weboglobin.com
|
73
|
+
licenses: []
|
74
|
+
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: "0"
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
none: false
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: "0"
|
92
|
+
requirements: []
|
93
|
+
|
94
|
+
rubyforge_project:
|
95
|
+
rubygems_version: 1.8.9
|
96
|
+
signing_key:
|
97
|
+
specification_version: 3
|
98
|
+
summary: This gem is a ruby client for the SemRush API.
|
99
|
+
test_files: []
|
100
|
+
|