Skip to content

Commit

Permalink
Add report 'phrase_organic' + 'display_sort' & 'display_filter' param…
Browse files Browse the repository at this point in the history
…eters
  • Loading branch information
arambert committed Jun 10, 2013
1 parent d2f713f commit 33d01d3
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 93 deletions.
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -21,7 +21,7 @@ require "rspec/core/rake_task"
desc "Run all test with spec"
RSpec::Core::RakeTask.new(:spec) do |t|
t.rspec_opts = %w[--color]
t.pattern = 'spec/*_spec.rb'
t.pattern = 'spec/**/*_spec.rb'
end
desc "Run tests"
task :default => :spec
3 changes: 2 additions & 1 deletion lib/semrush.rb
@@ -1,4 +1,5 @@
require 'uri'
require 'cgi'
require 'net/http'
require 'csv'
require 'rubygems'
Expand All @@ -8,7 +9,7 @@
require 'semrush/report'

module Semrush
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%"
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%&display_sort=%DISPLAY_SORT%&display_filter=%DISPLAY_FILTER%"
API_UNITS_URL = "http://www.semrush.com/users/countapiunits.html?key=%API_KEY%"
mattr_accessor :api_key
@@api_key = ""
Expand Down
31 changes: 24 additions & 7 deletions lib/semrush/report.rb
Expand Up @@ -9,7 +9,7 @@ module Semrush
class Report
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.
REPORT_TYPES = [:domain_rank, :domain_organic, :domain_adwords, :domain_organic_organic, :domain_adwords_adwords, :domain_organic_adwords, :domain_adwords_organic,
:phrase_this, :phrase_related,
:phrase_this, :phrase_organic, :phrase_related,
:url_organic, :url_adwords]
REQUEST_TYPES = [:domain, :phrase, :url]

Expand Down Expand Up @@ -111,7 +111,7 @@ def basics params = {}
domain? ? request(params.merge(:report_type => :domain_rank)) : request(params.merge(:report_type => :phrase_this))
end

# Organic Keywords report
# Organic report
# Can be called for a domain or a URL.
# Default columns for a domain:
# * Ph - The search query which the site has within the first 20 Google search results
Expand All @@ -135,11 +135,22 @@ def basics params = {}
# * 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
# * Nr - The number of search results - how many pages does Google know for this query
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
# Default columns for a phrase:
# * Dn - A site name
# * Ur - Target URL
def organic params = {}
case
when url? then request(params.merge(:report_type => :url_organic))
when phrase? then request(params.merge(:report_type => :phrase_organic))
else request(params.merge(:report_type => :domain_organic))
end
end
def keywords_organic params = {}
url? ? request(params.merge(:report_type => :url_organic)) : request(params.merge(:report_type => :domain_organic))
warn "[DEPRECATION] `keywords_organic` is deprecated. Please use `organic` instead."
organic(params)
end

# AdWords keywords report
# AdWords report
# Can be called for a domain or a URL.
# Default columns for a domain:
# * Ph - Search query which the site buys in AdWords in Google
Expand All @@ -164,9 +175,13 @@ def keywords_organic params = {}
# * 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
# * Nr - The number of search results - how many pages does Google know for this query
# * Td - Dynamics of change in the number of search queries in the past 12 months (estimated)
def keywords_adwords params = {}
def adwords params = {}
url? ? request(params.merge(:report_type => :url_adwords)) : request(params.merge(:report_type => :domain_adwords))
end
def keywords_adwords params = {}
warn "[DEPRECATION] `keywords_adwords` is deprecated. Please use `adwords` instead."
adwords(params)
end

# Competitors in organic search report
# Default columns:
Expand Down Expand Up @@ -237,7 +252,7 @@ def request params = {}
if v.blank?
temp_url.gsub!(/&[^&=]+=%#{k.to_s}%/i, '')
else
temp_url.gsub!("%#{k.to_s.upcase}%", URI.escape(v.to_s).gsub('&', '%26'))
temp_url.gsub!("%#{k.to_s.upcase}%", URI.escape(v.to_s).gsub('&', '%26').gsub('+', '%2B'))
end
}
puts "[Semrush query] URL: #{temp_url}" if Semrush.debug
Expand All @@ -261,14 +276,16 @@ def request params = {}
# * limit - number of results returned
# * offset - says to skip that many results before beginning to return results to you
# * export_columns - list of column names, separated by coma. You may list just the column names you need in an order you need.
# * display_sort - a sorting as a String eg: 'am_asc' or 'am_desc'(read http://www.semrush.com/api)
# * display_filter - list of filters separated by "|" (maximum number - 25). A filter consists of <sign>|<field>|<operation>|<value> (read http://www.semrush.com/api)
#
# more details in http://www.semrush.com/api.html
def validate_parameters params = {}
params.symbolize_keys!
params.delete(:db) unless DBS.include?(params[:db].try(:to_sym))
params.delete(:report_type) unless REPORT_TYPES.include?(params[:report_type].try(:to_sym))
params.delete(:request_type) unless REQUEST_TYPES.include?(params[:request_type].try(:to_sym))
@parameters = {:db => "us", :api_key => Semrush.api_key, :limit => "", :offset => "", :export_columns => ""}.merge(@parameters).merge(params)
@parameters = {:db => "us", :api_key => Semrush.api_key, :limit => "", :offset => "", :export_columns => "", :display_sort => "", :display_filter => ""}.merge(@parameters).merge(params)
raise Semrush::Exception::Nolimit.new(self, "The limit parameter is missing: a limit is required.") unless @parameters[:limit].present? && @parameters[:limit].to_i>0
raise Semrush::Exception::BadArgument.new(self, "Request parameter is missing: Domain name, URL, or keywords are required.") unless @parameters[:request].present?
raise Semrush::Exception::BadArgument.new(self, "Bad db: #{@parameters[:db]}") unless DBS.include?(@parameters[:db].try(:to_sym))
Expand Down
109 changes: 109 additions & 0 deletions spec/semrush/report_spec.rb
@@ -0,0 +1,109 @@
require 'spec_helper'

describe "Reports:" do
before(:all) do #once (and could be modified by the following tests)
Semrush.config do |config|
config.api_key = API_KEY
config.debug = true
end
end

describe Semrush, "running basic reports" do
it "works with the root method 'domain_rank'" do
lambda{Semrush::Report.new.domain_rank(:request_type => :domain, :request => "seobook.com", :db => :us, :limit => 5)}.should_not raise_error
end
end

describe Semrush, "running domain reports" do
it "initializes correctly" do
lambda{Semrush::Report.domain("seobook.com", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.domain("seobook.com", :db => :us)}.should_not raise_error
end
[:basics, :organic, :adwords].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.domain("seobook.com").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end

end

describe Semrush, "running url reports" do
it "initializes correctly" do
lambda{Semrush::Report.url("http://tools.seobook.com/", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.url("http://tools.seobook.com/", :db => :us)}.should_not raise_error
end
[:organic, :adwords].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.url("http://tools.seobook.com/").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end
[:basics, :competitors_organic, :competitors_adwords, :competitors_organic_by_adwords, :competitors_adwords_by_organic].each do |method|
it "should not work with the method '#{method}'" do
lambda{@parsed = Semrush::Report.url("http://tools.seobook.com/").send(method, :db => :us, :limit => 5)}.should raise_error
end
end
end

describe Semrush, "running phrase reports" do
it "initializes correctly" do
lambda{Semrush::Report.phrase("search+engine+optimization", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.phrase("search+engine+optimization", :db => :us)}.should_not raise_error
end
[:basics, :related, :organic].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.phrase("search+engine+optimization").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end
[:basics, :related].each do |method|
it "deals correctly with & in phrase" do
lambda{Semrush::Report.phrase("calvin & hobbs").send(method, :db => :us, :limit => 5)}.should_not raise_error
end
end
end

describe Semrush, "parameters positions in reports" do
it "could be set in the class method" do
lambda{Semrush::Report.domain("seobook.com", :db => :fr, :limit => 5, :offset => 2)}.should_not raise_error
end
it "could be set in the instance method" do
lambda{Semrush::Report.domain("seobook.com").organic(:db => :fr, :limit => 5, :offset => 2)}.should_not raise_error
end
it "both methods get the same results" do
in_class = Semrush::Report.domain("seobook.com", :db => :fr, :limit => 5, :offset => 2).organic
in_object = Semrush::Report.domain("seobook.com").organic(:db => :fr, :limit => 5, :offset => 2)
in_class.should == in_object
end
end

describe Semrush, "using display_sort parameter" do
it "works with domain_organic" do
lambda{Semrush::Report.domain("wikipedia.org", :limit => 5, :display_sort => 'tr_asc').organic}.should_not raise_error
end
end
describe Semrush, "using display_filter parameter" do
it "returns an Array with elements if Po<5" do
r = Semrush::Report.domain("wikipedia.org", :limit => 5, :display_filter => '+|Po|Lt|5').organic
r.should be_a_kind_of Array
r.count.should > 0
end
it "returns empty Array if Po<1" do
Semrush::Report.domain("wikipedia.org", :limit => 5, :display_filter => '+|Po|Lt|1').organic.should == []
end
end

end
86 changes: 2 additions & 84 deletions spec/semrush_spec.rb
@@ -1,5 +1,4 @@
require 'spec_helper'
API_KEY = ENV['API_KEY'] || "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

describe Semrush, "config" do
it "comes from a module" do #simple test to init tests
Expand All @@ -13,6 +12,7 @@
}.should raise_error(Semrush::Exception::BadApiKey)
end
end

describe "Requests:" do
before(:all) do #once (and could be modified by the following tests)
Semrush.config do |config|
Expand All @@ -32,12 +32,6 @@
end
end

describe Semrush, "running basic reports" do
it "works with the root method 'domain_rank'" do
lambda{Semrush::Report.new.domain_rank(:request_type => :domain, :request => "seobook.com", :db => :us, :limit => 5)}.should_not raise_error
end
end

describe Semrush, "log reports with before & after" do
before(:all) do #once (and could be modified by the following tests)
Semrush.config do |config|
Expand All @@ -48,84 +42,8 @@
end
end
it "works" do
lambda{Semrush::Report.domain("seobook.com", :db => :us).keywords_organic(:limit => 5)}.should_not raise_error
end
end

describe Semrush, "running domain reports" do
it "initializes correctly" do
lambda{Semrush::Report.domain("seobook.com", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.domain("seobook.com", :db => :us)}.should_not raise_error
end
[:basics, :keywords_organic, :keywords_adwords].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.domain("seobook.com").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end

end

describe Semrush, "running url reports" do
it "initializes correctly" do
lambda{Semrush::Report.url("http://tools.seobook.com/", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.url("http://tools.seobook.com/", :db => :us)}.should_not raise_error
end
[:keywords_organic, :keywords_adwords].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.url("http://tools.seobook.com/").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end
[:basics, :competitors_organic, :competitors_adwords, :competitors_organic_by_adwords, :competitors_adwords_by_organic].each do |method|
it "should not work with the method '#{method}'" do
lambda{@parsed = Semrush::Report.url("http://tools.seobook.com/").send(method, :db => :us, :limit => 5)}.should raise_error
end
end
end

describe Semrush, "running phrase reports" do
it "initializes correctly" do
lambda{Semrush::Report.phrase("search+engine+optimization", :db => :us)}.should_not raise_error
end
it "initializes correctly with params" do
lambda{Semrush::Report.phrase("search+engine+optimization", :db => :us)}.should_not raise_error
end
[:basics, :related].each do |method|
it "works with the method '#{method}'" do
lambda{@parsed = Semrush::Report.phrase("search+engine+optimization").send(method, :db => :us, :limit => 5)}.should_not raise_error
@parsed.should_not be_nil
@parsed.should be_a_kind_of(Array)
@parsed.first.should be_a_kind_of(Hash) if !@parsed.first.nil?
end
end
[:basics, :related].each do |method|
it "deals correctly with & in phrase" do
lambda{Semrush::Report.phrase("calvin & hobbs").send(method, :db => :us, :limit => 5)}.should_not raise_error
end
lambda{Semrush::Report.domain("seobook.com", :db => :us).organic(:limit => 5)}.should_not raise_error
end
end

describe Semrush, "parameters in reports" do
it "could be set in the class method" do
lambda{Semrush::Report.domain("seobook.com", :db => :fr, :limit => 5, :offset => 2)}.should_not raise_error
end
it "could be set in the instance method" do
lambda{Semrush::Report.domain("seobook.com").keywords_organic(:db => :fr, :limit => 5, :offset => 2)}.should_not raise_error
end
it "both methods get the same results" do
in_class = Semrush::Report.domain("seobook.com", :db => :fr, :limit => 5, :offset => 2).keywords_organic
in_object = Semrush::Report.domain("seobook.com").keywords_organic(:db => :fr, :limit => 5, :offset => 2)
in_class.should == in_object
end

end
end
1 change: 1 addition & 0 deletions spec/spec_helper.rb
Expand Up @@ -2,6 +2,7 @@
require 'bundler/setup'

require 'semrush' # and any other gems you need
API_KEY = ENV['API_KEY'] || "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

RSpec.configure do |config|
# some (optional) config here
Expand Down

0 comments on commit 33d01d3

Please sign in to comment.