email_tracker 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +26 -0
- data/Rakefile +40 -0
- data/app/assets/images/email_tracker/transparent.png +0 -0
- data/app/assets/javascripts/email_tracker/application.js +15 -0
- data/app/assets/stylesheets/email_tracker/application.css +13 -0
- data/app/controllers/email_tracker/application_controller.rb +4 -0
- data/app/controllers/email_tracker/email_instances_controller.rb +31 -0
- data/app/controllers/email_tracker/link_instances_controller.rb +43 -0
- data/app/helpers/email_tracker/application_helper.rb +4 -0
- data/app/models/email_tracker/email.rb +85 -0
- data/app/models/email_tracker/email_instance.rb +32 -0
- data/app/models/email_tracker/interceptor.rb +65 -0
- data/app/models/email_tracker/link.rb +10 -0
- data/app/models/email_tracker/link_instance.rb +31 -0
- data/app/views/layouts/email_tracker/application.html.erb +14 -0
- data/config/initializers/email_tracker.rb +34 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20120610201855_create_email_tracker_emails.rb +18 -0
- data/db/migrate/20120610202021_create_email_tracker_email_instances.rb +19 -0
- data/db/migrate/20120610202122_create_email_tracker_links.rb +12 -0
- data/db/migrate/20120610202149_create_email_tracker_link_instances.rb +16 -0
- data/lib/email_tracker.rb +4 -0
- data/lib/email_tracker/engine.rb +5 -0
- data/lib/email_tracker/version.rb +3 -0
- data/lib/tasks/email_tracker_tasks.rake +4 -0
- metadata +126 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 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,26 @@
|
|
1
|
+
= Email Tracker
|
2
|
+
|
3
|
+
This engine tracks emails in your Ruby on Rails app.
|
4
|
+
|
5
|
+
== Licence
|
6
|
+
|
7
|
+
Copyright 2012 Jeremy Walker
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
10
|
+
a copy of this software and associated documentation files (the
|
11
|
+
"Software"), to deal in the Software without restriction, including
|
12
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
13
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
+
permit persons to whom the Software is furnished to do so, subject to
|
15
|
+
the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be
|
18
|
+
included in all copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'EmailTracker'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
|
32
|
+
Rake::TestTask.new(:test) do |t|
|
33
|
+
t.libs << 'lib'
|
34
|
+
t.libs << 'test'
|
35
|
+
t.pattern = 'test/**/*_test.rb'
|
36
|
+
t.verbose = false
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
task :default => :test
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module EmailTracker
|
2
|
+
class EmailInstancesController < ApplicationController
|
3
|
+
|
4
|
+
skip_before_filter :check_logged_in, :only => :opened
|
5
|
+
|
6
|
+
def opened
|
7
|
+
# Get the instance from the url code
|
8
|
+
@instance = EmailTracker::EmailInstance.where(url_code: params[:url_code]).order("id DESC").first
|
9
|
+
|
10
|
+
# If this hasn't been found, it may be due to a legacy issue
|
11
|
+
# where we used to search by id
|
12
|
+
unless @instance
|
13
|
+
# Search by id
|
14
|
+
@instance = EmailTracker::EmailInstance.find_by_id(params[:url_code])
|
15
|
+
|
16
|
+
# If the instance doesn't exist, or it has a url code (and is therefore post this change) then get out of here
|
17
|
+
unless @instance && @instance.url_code == ""
|
18
|
+
redirect_to root_path
|
19
|
+
return
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Mark the instance as opened
|
24
|
+
@instance.opened!
|
25
|
+
|
26
|
+
# And send the required image data back
|
27
|
+
send_data(File.read(File.expand_path("../../../assets/images/email_tracker/transparent.png", __FILE__)))
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module EmailTracker
|
2
|
+
class LinkInstancesController < ApplicationController
|
3
|
+
|
4
|
+
skip_before_filter :check_logged_in, :only => :clicked
|
5
|
+
|
6
|
+
def clicked
|
7
|
+
# Get the instance from the url code
|
8
|
+
@instance = EmailTracker::LinkInstance.where(url_code: params[:url_code]).order("id DESC").first
|
9
|
+
|
10
|
+
# If this hasn't been found, it may be due to a legacy issue
|
11
|
+
# where we used to search by id
|
12
|
+
unless @instance
|
13
|
+
# Search by id
|
14
|
+
@instance = EmailTracker::LinkInstance.find_by_id(params[:url_code])
|
15
|
+
|
16
|
+
# If the instance doesn't exist, or it has a url code (and is therefore post this change) then get out of here
|
17
|
+
unless @instance && @instance.url_code == ""
|
18
|
+
redirect_to root_path
|
19
|
+
return
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# We have a valid instance, so mark it as clicked
|
24
|
+
@instance.clicked!
|
25
|
+
redirect_to @instance.link.url
|
26
|
+
|
27
|
+
=begin
|
28
|
+
# If we don't have a user model to care about, just leave
|
29
|
+
return unless Module.const_defined?(:User)
|
30
|
+
|
31
|
+
# Otherwise check whether the user can view this page and act accordingly
|
32
|
+
if @instance.is_externally_viewable? ||
|
33
|
+
!@instance.user ||
|
34
|
+
(responds_to(:user_logged_in?) && user_logged_in?) ||
|
35
|
+
(responds_to(:logged_in?) && logged_in?)
|
36
|
+
else
|
37
|
+
store_user_location(@instance.link.url)
|
38
|
+
@new_user = @instance.user
|
39
|
+
end
|
40
|
+
=end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module EmailTracker
|
2
|
+
class Email < ActiveRecord::Base
|
3
|
+
|
4
|
+
belongs_to :owner, polymorphic: true
|
5
|
+
|
6
|
+
has_many :instances, class_name: "EmailInstance"
|
7
|
+
has_many :link_instances, through: :instances
|
8
|
+
|
9
|
+
attr_accessible :owner, :owner_type, :owner_id, :mailer, :action, as: :email_tracker_internals
|
10
|
+
|
11
|
+
before_create :set_default_name
|
12
|
+
before_create :set_default_description
|
13
|
+
|
14
|
+
def self.for_email(data)
|
15
|
+
|
16
|
+
hash = {
|
17
|
+
mailer: data[:mailer],
|
18
|
+
action: data[:action],
|
19
|
+
owner_type: data[:owner_type],
|
20
|
+
owner_id: data[:owner_id]
|
21
|
+
}
|
22
|
+
|
23
|
+
if email = self.where(hash).first
|
24
|
+
return email
|
25
|
+
end
|
26
|
+
|
27
|
+
email = self.new(hash, as: :email_tracker_internals)
|
28
|
+
email.save!
|
29
|
+
email
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_instance!(email_address, user_id)
|
33
|
+
instances.create!({email_address: email_address, user_id: user_id}, as: :email_tracker_internals)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def set_default_name
|
39
|
+
self.name = if owner
|
40
|
+
if owner.respond_to?(:name)
|
41
|
+
owner.name
|
42
|
+
elsif owner.respond_to?(:title)
|
43
|
+
owner.title
|
44
|
+
else
|
45
|
+
"#{owner.class.name.humanize.capitalize} ##{owner.id}"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
"#{mailer.split("/").last.capitalize} #{action.humanize}"
|
49
|
+
end
|
50
|
+
true
|
51
|
+
end
|
52
|
+
|
53
|
+
def set_default_description
|
54
|
+
self.description = ""
|
55
|
+
true
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
=begin
|
60
|
+
|
61
|
+
|
62
|
+
def times_sent(since = nil)
|
63
|
+
i = instances
|
64
|
+
i = i.where("created_at > ?", since) if since
|
65
|
+
i.count
|
66
|
+
end
|
67
|
+
|
68
|
+
def times_opened(since = nil)
|
69
|
+
i = instances.opened
|
70
|
+
i = i.where("opened_at > ?", since) if since
|
71
|
+
i.count
|
72
|
+
end
|
73
|
+
|
74
|
+
def opened_percentage(since = nil)
|
75
|
+
((times_opened(since).to_f / times_sent(since)) * 100).to_i
|
76
|
+
end
|
77
|
+
|
78
|
+
def num_links_clicked(since = nil)
|
79
|
+
i = link_instances.clicked
|
80
|
+
i = i.where("clicked_at > ?", since) if since
|
81
|
+
i.count
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
=end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
module EmailTracker
|
3
|
+
class EmailInstance < ActiveRecord::Base
|
4
|
+
|
5
|
+
belongs_to :email
|
6
|
+
belongs_to :user
|
7
|
+
has_many :link_instances
|
8
|
+
|
9
|
+
attr_accessible :email_address, :user_id, as: :email_tracker_internals
|
10
|
+
|
11
|
+
scope :opened, where("opened_at IS NOT NULL")
|
12
|
+
|
13
|
+
before_create do
|
14
|
+
if Module.const_defined?(:User)
|
15
|
+
self.user = User.where(email: self.email_address).select(:id).first unless self.user_id
|
16
|
+
end
|
17
|
+
self.url_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def opened?
|
22
|
+
opened_at != nil ? true : false
|
23
|
+
end
|
24
|
+
|
25
|
+
def opened!
|
26
|
+
unless opened?
|
27
|
+
self.opened_at = DateTime.now
|
28
|
+
save!
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module EmailTracker
|
2
|
+
class Interceptor
|
3
|
+
def self.delivering_email(message)
|
4
|
+
|
5
|
+
if message.multipart?
|
6
|
+
message.html_part.body = add_tracking(message, message.html_part.body.to_s)
|
7
|
+
else
|
8
|
+
message.body = add_tracking(message, message.body.to_s)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.add_tracking(message, content)
|
13
|
+
begin
|
14
|
+
# Get tracking data, and the recipient
|
15
|
+
tracking_data = message.tracking_data
|
16
|
+
email_address = Array(message.to).first
|
17
|
+
|
18
|
+
if tracking_data[:owner]
|
19
|
+
tracking_data[:owner_type] = tracking_data[:owner].class.name
|
20
|
+
tracking_data[:owner_id] = tracking_data[:owner].id
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get or create a tracked version of this email
|
24
|
+
tracking_email = EmailTracker::Email.for_email(tracking_data)
|
25
|
+
|
26
|
+
# And create a new instance for this email address (and user if specified)
|
27
|
+
tracking_email_instance = tracking_email.create_instance!(email_address, tracking_data[:user_id])
|
28
|
+
|
29
|
+
# Get url options
|
30
|
+
opts = Rails.application.config.action_mailer.default_url_options
|
31
|
+
protocol = opts.fetch(:protocol, "http")
|
32
|
+
host = opts.fetch(:host)
|
33
|
+
url_base = "#{protocol}://#{host}/"
|
34
|
+
|
35
|
+
# Modify html to track open
|
36
|
+
tracking_url = "#{url_base}et_open/#{tracking_email_instance.url_code}.gif"
|
37
|
+
tracking_html = "<img src=\"#{tracking_url}\" alt=\"\"/>"
|
38
|
+
content.gsub!("<body>", "<body>#{tracking_html}")
|
39
|
+
|
40
|
+
# Modify html to track clicks
|
41
|
+
content.gsub!(/href\=['"]([^"']+)['"]/) do |match|
|
42
|
+
url = $1
|
43
|
+
if url.starts_with?("mailto")
|
44
|
+
match
|
45
|
+
elsif url.match("et_notrack=true")
|
46
|
+
""
|
47
|
+
else
|
48
|
+
if external = !!url.match("et_external=true")
|
49
|
+
url.gsub!("et_external=true", "")
|
50
|
+
end
|
51
|
+
|
52
|
+
tracked_link = EmailTracker::Link.for_url(url)
|
53
|
+
tracked_link_instance = tracked_link.instances.create!({email_instance: tracking_email_instance, is_externally_viewable: external}, as: :email_tracker_internals)
|
54
|
+
url = "#{url_base}et_click/#{tracked_link_instance.url_code}"
|
55
|
+
"href=\"#{url}\""
|
56
|
+
end
|
57
|
+
end
|
58
|
+
rescue
|
59
|
+
p $!
|
60
|
+
end
|
61
|
+
|
62
|
+
content
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
'digest/sha1'
|
2
|
+
module EmailTracker
|
3
|
+
class LinkInstance < ActiveRecord::Base
|
4
|
+
|
5
|
+
belongs_to :email_instance
|
6
|
+
has_one :email, through: :email_instance
|
7
|
+
has_one :user, through: :email_instance
|
8
|
+
belongs_to :link
|
9
|
+
|
10
|
+
attr_accessible :email_instance, :is_externally_viewable, as: :email_tracker_internals
|
11
|
+
|
12
|
+
scope :clicked, where("clicked_at IS NOT NULL")
|
13
|
+
|
14
|
+
before_create do
|
15
|
+
self.url_code = Digest::SHA1.hexdigest( Time.now.to_s.split(//).sort_by {rand}.join )
|
16
|
+
end
|
17
|
+
|
18
|
+
def clicked?
|
19
|
+
clicked_at != nil ? true : false
|
20
|
+
end
|
21
|
+
|
22
|
+
def clicked!
|
23
|
+
unless clicked?
|
24
|
+
self.clicked_at = DateTime.now
|
25
|
+
save!
|
26
|
+
end
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>EmailTracker</title>
|
5
|
+
<%= stylesheet_link_tag "email_tracker/application", :media => "all" %>
|
6
|
+
<%= javascript_include_tag "email_tracker/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'mail'
|
2
|
+
|
3
|
+
# Register the interceptor, observer and subscribers
|
4
|
+
# These all do different things to the message at different stages
|
5
|
+
Mail.register_interceptor(EmailTracker::Interceptor)
|
6
|
+
|
7
|
+
# Add a private variable :tracking_data
|
8
|
+
class Mail::Message
|
9
|
+
attr_accessor :tracking_data
|
10
|
+
end
|
11
|
+
|
12
|
+
class ActionMailer::Base
|
13
|
+
alias_method :mail_without_tracking, :mail
|
14
|
+
|
15
|
+
# Modifies mail() so headers can take the hash :tracking_data
|
16
|
+
# which contains extra data to be tracked
|
17
|
+
def mail(headers = {}, &block)
|
18
|
+
|
19
|
+
# Extra tracking data can be passed via :tracking_data in the headers
|
20
|
+
tracking_data = headers.delete(:tracking_data) || {}
|
21
|
+
|
22
|
+
# Store the mailer as the current class name underscored
|
23
|
+
tracking_data[:mailer] ||= self.class.name.underscore
|
24
|
+
|
25
|
+
# Store the action as the method that has called mail()
|
26
|
+
# This can be overriden by passing :action as part of tracking_data
|
27
|
+
tracking_data[:action] ||= caller[0][/`([^']*)'/, 1]
|
28
|
+
|
29
|
+
# Call the original method and add the tracking_data
|
30
|
+
message = mail_without_tracking(headers, &block)
|
31
|
+
message.tracking_data = tracking_data
|
32
|
+
message
|
33
|
+
end
|
34
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
match "et_open/:url_code" => "email_tracker/email_instances#opened", as: "email_tracking_email_opened"
|
3
|
+
match "et_click/:url_code" => "email_tracker/link_instances#clicked", as: "email_tracking_link_clicked"
|
4
|
+
end
|
5
|
+
|
6
|
+
EmailTracker::Engine.routes.draw do
|
7
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateEmailTrackerEmails < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :email_tracker_emails do |t|
|
4
|
+
|
5
|
+
t.string :name, null:true
|
6
|
+
t.text :description, null:true
|
7
|
+
|
8
|
+
t.string :mailer, null: false
|
9
|
+
t.string :action, null: false
|
10
|
+
|
11
|
+
t.string :owner_type, null: true
|
12
|
+
t.integer :owner_id, null: true
|
13
|
+
|
14
|
+
t.datetime :created_at, null:false
|
15
|
+
t.datetime :updated_at, null:false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateEmailTrackerEmailInstances < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :email_tracker_email_instances do |t|
|
4
|
+
|
5
|
+
t.integer :email_id, null:false
|
6
|
+
|
7
|
+
t.string :email_address, null: false
|
8
|
+
t.string :url_code, null: false
|
9
|
+
t.integer :user_id, null: true
|
10
|
+
|
11
|
+
t.datetime :created_at, null:false
|
12
|
+
t.datetime :updated_at, null:false
|
13
|
+
t.datetime :opened_at, null:true
|
14
|
+
end
|
15
|
+
|
16
|
+
#add_foreign_key :email_tracking_email_instances, :email_tracking_emails, column: :email_id
|
17
|
+
#add_foreign_key :email_tracking_email_instances, :users, column: :user_id
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateEmailTrackerLinks < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :email_tracker_links do |t|
|
4
|
+
t.string :url, null: false
|
5
|
+
|
6
|
+
t.integer :num_clicks, null: false, default: 0
|
7
|
+
|
8
|
+
t.datetime :created_at, null: false
|
9
|
+
t.datetime :updated_at, null: false
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateEmailTrackerLinkInstances < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :email_tracker_link_instances do |t|
|
4
|
+
t.integer :link_id, null: false
|
5
|
+
t.integer :email_instance_id, null: false
|
6
|
+
|
7
|
+
t.string :url_code, null: false
|
8
|
+
t.boolean :is_externally_viewable, null: false, default: false
|
9
|
+
|
10
|
+
t.datetime :clicked_at, null: true
|
11
|
+
end
|
12
|
+
|
13
|
+
#add_foreign_key :email_tracking_link_instances, :email_tracking_links, column: :link_id
|
14
|
+
#add_foreign_key :email_tracking_link_instances, :email_tracking_email_instances, column: :email_instance_id
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: email_tracker
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Walker
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-10 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: &70299321339740 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70299321339740
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sqlite3
|
27
|
+
requirement: &70299321337920 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70299321337920
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec-rails
|
38
|
+
requirement: &70299321334620 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70299321334620
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: factory_girl_rails
|
49
|
+
requirement: &70299321348520 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70299321348520
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: webrat
|
60
|
+
requirement: &70299321345960 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70299321345960
|
69
|
+
description: A plugin for Rails apps that track email.
|
70
|
+
email:
|
71
|
+
- jez.walker@gmail.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- app/assets/images/email_tracker/transparent.png
|
77
|
+
- app/assets/javascripts/email_tracker/application.js
|
78
|
+
- app/assets/stylesheets/email_tracker/application.css
|
79
|
+
- app/controllers/email_tracker/application_controller.rb
|
80
|
+
- app/controllers/email_tracker/email_instances_controller.rb
|
81
|
+
- app/controllers/email_tracker/link_instances_controller.rb
|
82
|
+
- app/helpers/email_tracker/application_helper.rb
|
83
|
+
- app/models/email_tracker/email.rb
|
84
|
+
- app/models/email_tracker/email_instance.rb
|
85
|
+
- app/models/email_tracker/interceptor.rb
|
86
|
+
- app/models/email_tracker/link.rb
|
87
|
+
- app/models/email_tracker/link_instance.rb
|
88
|
+
- app/views/layouts/email_tracker/application.html.erb
|
89
|
+
- config/initializers/email_tracker.rb
|
90
|
+
- config/routes.rb
|
91
|
+
- db/migrate/20120610201855_create_email_tracker_emails.rb
|
92
|
+
- db/migrate/20120610202021_create_email_tracker_email_instances.rb
|
93
|
+
- db/migrate/20120610202122_create_email_tracker_links.rb
|
94
|
+
- db/migrate/20120610202149_create_email_tracker_link_instances.rb
|
95
|
+
- lib/email_tracker/engine.rb
|
96
|
+
- lib/email_tracker/version.rb
|
97
|
+
- lib/email_tracker.rb
|
98
|
+
- lib/tasks/email_tracker_tasks.rake
|
99
|
+
- MIT-LICENSE
|
100
|
+
- Rakefile
|
101
|
+
- README.rdoc
|
102
|
+
homepage: http://www.ihid.co.uk/email_tracker
|
103
|
+
licenses: []
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
none: false
|
110
|
+
requirements:
|
111
|
+
- - ! '>='
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '0'
|
114
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 1.8.10
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: A plugin for Rails apps that track email.
|
126
|
+
test_files: []
|