Class: Rack::Referrals

Inherits:
Object
  • Object
show all
Defined in:
lib/rack-referrals.rb,
lib/rack-referrals/version.rb

Overview

Rack Middleware for extracting information from the HTTP-REFERER header. Specifically, it populates env and env if it detects a request came from a known search engine.

Constant Summary collapse

DEFAULT_ENGINES =
{
  # Tested myself
  :google     => [/^https?:\/\/(www\.)?google.*/, 'q'],
  :yahoo      => [/^https?:\/\/([^\.]+.)?search\.yahoo.*/, 'p'],
  :bing       => [/^https?:\/\/search\.bing.*/, 'q'],
  :biadu      => [/^https?:\/\/(www\.)?baidu.*/, 'wd'],
  :rambler    => [/^https?:\/\/([^\.]+.)?rambler.ru/, 'query'],
  :yandex     => [/^https?:\/\/(www\.)?yandex.ru/, 'text'],      

  # Borrowed from https://github.com/squeejee/search_sniffer
  :msn        => [/^https?:\/\/search\.msn.*/, 'q'],
  :aol        => [/^https?:\/\/(www\.)?\.aol.*/, 'query'],
  :altavista  => [/^https?:\/\/(www\.)?altavista.*/, 'q'],
  :feedster   => [/^https?:\/\/(www\.)?feedster.*/, 'q'],
  :lycos      => [/^https?:\/\/search\.lycos.*/, 'query'],
  :alltheweb  => [/^https?:\/\/(www\.)?alltheweb.*/, 'q'] 
  
  # Want to add support for more? A good place to start would be this list (note that they
  # give example domains, though, not anything we can use to construct a reliable reg exp):
  # http://code.google.com/apis/analytics/docs/tracking/gaTrackingTraffic.html#searchEngine
}
VERSION =
"0.0.2"

Instance Method Summary collapse

Constructor Details

#initialize(app, opts = {}) ⇒ Referrals

Returns a new instance of Referrals.



35
36
37
38
39
40
# File 'lib/rack-referrals.rb', line 35

def initialize(app, opts = {})
  @app = app
  
  @engines   = opts[:engines]
  @engines ||= DEFAULT_ENGINES.merge(opts[:additional_engines] || {})
end

Instance Method Details

#call(env) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/rack-referrals.rb', line 42

def call(env)
  request = Rack::Request.new(env)
  from = request.env["HTTP_REFERER"]
  
  if from.to_s.length > 0
    if engine = @engines.detect {|name, data| from =~ data[0] }
      env["referring.search_engine"] = engine[0].to_s
      reg, param_name = engine[1]
      
      # Pull out the query string from the referring search engine
      query_string = begin
        URI.split(from)[7]
      rescue URI::InvalidURIError; nil
      end
      
      env["referring.search_terms"] = query_string && Rack::Utils.parse_query(query_string)[param_name]
    end
  end
  
  @app.call(env)
end