touchstone 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -18,7 +18,7 @@ Add the following line to your Gemfile:
18
18
 
19
19
  Then run `bundle install`
20
20
 
21
- Copy the migrations across to your application by running `touchstone:install:migrations`. This will add a models for the 3 elements set out above.
21
+ Copy the migrations across to your application by running `touchstone:install:migrations`. This will add models for the 3 elements set out above.
22
22
 
23
23
  You will need to mount Touchstone in your application by adding the following line to your `routes.rb` file:
24
24
 
@@ -42,7 +42,7 @@ Finally, add the following to your `application_controller.rb` file:
42
42
  ## Usage
43
43
  Usage is very simple. Assume you are running a Google Adwords campaign for 1 week at a cost of $100. Create this campaign in Touchstone and it will return a campaign ID. Make sure all your links on Adwords contain the parameter at the end `?cid={campaign_id}` where `campaign_id` is the id generated by Touchstone. Please note:
44
44
 
45
- * Campaigns don't need to be paid campaigns, it can be as simple as a link from your homepage or multiple links if A/B testing
45
+ * Campaigns don't need to be paid campaigns, it can be as simple as a link on your homepage
46
46
  * You can update the campaign cost at any time. All calculations are "on the fly" so you're metrics will update automatically
47
47
 
48
48
  The installation steps described above will get you going with tracking visits from particular campaigns but you still have some work to do in linking this to your users. Touchstone only really provides a benefit when you track how much revenue your users bring in and then it will compare that to the cost of your campaigns. By way of examples only, you could adopt the following pattern to record a campaign signup:
@@ -81,4 +81,5 @@ Tracking a user's lifetime value will depend on your transactional logic but ass
81
81
  * Don't constrain Touchstone to an application that only has a Users table. Allow this as a configuration option
82
82
  * Automatically load routes and application controller content
83
83
  * Improve design
84
- * Add some tests
84
+ * Add some tests
85
+ * Allow customisation of currency (only displays dollars at moment although amounts are not stored in a particular currency)
@@ -0,0 +1,71 @@
1
+ $iconSpritePath: asset-url('glyphicons-halflings.png',image);
2
+ $iconWhiteSpritePath: asset-url('glyphicons-halflings-white.png',image);
3
+ @import "bootstrap";
4
+ body { padding-top: 60px; }
5
+ @import "bootstrap-responsive";
6
+
7
+ /* Mixins */
8
+
9
+ @mixin float-right {
10
+ float: right;
11
+ margin: 0 5px;
12
+ }
13
+
14
+ /* Bootstrap Extensions */
15
+
16
+ .touchstone .page-header .btn {
17
+ @include float-right;
18
+ }
19
+
20
+ .alert {
21
+ text-align: center;
22
+ padding-bottom: 0px;
23
+ }
24
+
25
+ /* Styles */
26
+
27
+ .touchstone .navbar .brand {
28
+ font-weight: bold;
29
+ }
30
+
31
+ .touchstone .navbar .brand a {
32
+ color: rgb(0,0,0);
33
+ text-shadow: rgba(255,255,255,0.125) 0px 1px 0px;
34
+ text-decoration: none;
35
+ }
36
+
37
+ .touchstone .navbar .brand a:hover {
38
+ text-shadow: rgba(255,255,255,0.25) 0 0px 2px;
39
+ }
40
+
41
+ .touchstone {
42
+ font: 62.5% "Helvetica Neue", "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
43
+ font-weight: normal;
44
+ -webkit-text-shadow: 0px -1px 0px rgb(68,68,68);
45
+ }
46
+
47
+ .touchstone th,
48
+ .touchstone td {
49
+ font-size: 1.4em;
50
+ }
51
+
52
+ .touchstone .controls select:first-child,
53
+ .touchstone .controls select:last-child {
54
+ width: 60px;
55
+ }
56
+
57
+ .touchstone .controls select:nth-child(2) {
58
+ width: 140px;
59
+ }
60
+
61
+ .touchstone #financials {
62
+ margin-bottom: 10px;
63
+ }
64
+
65
+ .touchstone .stats span {
66
+ color: rgb(0,115,204);
67
+ }
68
+
69
+ .touchstone #visits {
70
+ margin-bottom: 20px;
71
+ }
@@ -25,4 +25,19 @@ class Touchstone::CampaignsController < ApplicationController
25
25
  @campaign = Campaign.find(params[:id])
26
26
  end
27
27
 
28
+ def edit
29
+ @campaign = Campaign.find(params[:id])
30
+ end
31
+
32
+ def update
33
+ @campaign = Campaign.find(params[:id])
34
+ if @campaign.update_attributes(params[:campaign]) && @campaign.save
35
+ flash[:notice] = "Campaign details updated"
36
+ redirect_to campaign_path(@campaign)
37
+ else
38
+ flash[:error] = "Could not update details at this time."
39
+ redirect_to campaign_path(@campaign)
40
+ end
41
+ end
42
+
28
43
  end
@@ -7,16 +7,32 @@
7
7
  <%= csrf_meta_tag %>
8
8
  </head>
9
9
  <body class="touchstone">
10
- <div class="wrapper">
11
-
12
- <section id="flash">
13
- <% flash.each do |key, value| -%>
14
- <div id="flash_<%= key %>"><%= value.html_safe %></div>
15
- <% end -%>
16
- </section>
17
-
18
- <%= yield %>
19
-
20
- </div><!-- .wrapper -->
10
+ <header class="navbar navbar-fixed-top">
11
+ <nav class="navbar-inner">
12
+ <div class="container">
13
+ <h1 class="brand"><%= link_to "Touchstone Metrics", root_url %></h1>
14
+ </div>
15
+ </nav>
16
+ </header>
17
+ <div id="main" role="main">
18
+ <div class="container">
19
+ <div class="content">
20
+ <div class="row">
21
+ <div class="span12">
22
+ <% flash.each do |key, value| -%>
23
+ <div class="alert alert-<%= key %>">
24
+ <a class="close" data-dismiss="alert">×</a>
25
+ <p><%= value.html_safe %></p>
26
+ </div><!-- eo .alert -->
27
+ <% end -%>
28
+
29
+ <%= yield %>
30
+ </div><!-- eo .span12 -->
31
+ </div><!-- eo .row -->
32
+ </div><!-- eo .content -->
33
+ <footer>
34
+ </footer>
35
+ </div> <!--! end of .container -->
36
+ </div> <!--! end of #main -->
21
37
  </body>
22
38
  </html>
@@ -0,0 +1,42 @@
1
+ <%= form_for @campaign, :html => {:class => "well span6"} do |f| %>
2
+
3
+ <div class="control-group">
4
+ <%= f.label :name, :class => "control-label" %>
5
+ <div class="controls">
6
+ <%= f.text_field :name %>
7
+ </div><!-- eo .controls -->
8
+ </div><!-- eo .control-group -->
9
+
10
+ <div class="control-group">
11
+ <%= f.label :notes, :class => "control-label" %>
12
+ <div class="controls">
13
+ <%= f.text_area :notes, :class => "span6", :rows => 5 %>
14
+ </div><!-- eo .controls -->
15
+ </div><!-- eo .control-group -->
16
+
17
+ <div class="control-group">
18
+ <%= f.label :start_date, :class => "control-label" %>
19
+ <div class="controls">
20
+ <%= f.date_select :start_date, :order => [:day, :month, :year] %>
21
+ </div><!-- eo .controls -->
22
+ </div><!-- eo .control-group -->
23
+
24
+ <div class="control-group">
25
+ <%= f.label :end_date, :class => "control-label" %>
26
+ <div class="controls">
27
+ <%= f.date_select :end_date, :order => [:day, :month, :year] %>
28
+ </div><!-- eo .controls -->
29
+ </div><!-- eo .control-group -->
30
+
31
+ <div class="control-group">
32
+ <%= f.label :spend_amount, :class => "control-label" %>
33
+ <div class="controls">
34
+ <%= f.text_field :spend_amount %>
35
+ </div><!-- eo .controls -->
36
+ </div><!-- eo .control-group -->
37
+
38
+ <p>
39
+ <%= f.submit :class => "btn btn-primary" %> or <%= link_to "cancel", campaigns_path %>
40
+ </p>
41
+
42
+ <% end %>
@@ -0,0 +1,3 @@
1
+ <div class="page-header"><h1>Edit Campaign</h1></div>
2
+
3
+ <%= render :partial => 'campaign_form' %>
@@ -1,8 +1,9 @@
1
- <p id="new-campaign"><%= link_to "New campaign", new_campaign_url %></p>
1
+ <div class="page-header">
2
+ <%= link_to "<i class='icon-plus icon-white'></i>&nbsp;New campaign".html_safe, new_campaign_url, :class => "btn btn-primary" %>
3
+ <h1>Campaigns</h1>
4
+ </div><!-- eo .page-header -->
2
5
 
3
- <h1>Campaigns</h1>
4
-
5
- <table>
6
+ <table class="table table-striped">
6
7
  <thead>
7
8
  <tr>
8
9
  <th scope="col" width="15%">Campaign ID</th>
@@ -1,29 +1,3 @@
1
- <h1>New campaign</h1>
1
+ <div class="page-header"><h1>New campaign</h1></div>
2
2
 
3
- <%= form_for @campaign do |f| %>
4
-
5
- <p>
6
- <%= f.label :name %>
7
- <%= f.text_field :name %>
8
- </p>
9
- <p>
10
- <%= f.label :notes %>
11
- <%= f.text_area :notes %>
12
- </p>
13
- <p>
14
- <%= f.label :start_date %>
15
- <%= f.date_select :start_date, :order => [:day, :month, :year] %>
16
- </p>
17
- <p>
18
- <%= f.label :end_date %>
19
- <%= f.date_select :end_date, :order => [:day, :month, :year] %>
20
- </p>
21
- <p>
22
- <%= f.label :spend_amount %>
23
- <%= f.text_field :spend_amount %>
24
- </p>
25
- <p>
26
- <%= f.submit "Create campaign" %>
27
- </p>
28
-
29
- <% end %>
3
+ <%= render :partial => 'campaign_form' %>
@@ -1,27 +1,31 @@
1
- <p><%= link_to "Home", campaigns_url %></p>
2
-
3
- <h1>Campaign - <%= @campaign.name %></h1>
1
+ <div class="page-header">
2
+ <%= link_to "<i class='icon-pencil'></i>&nbsp;Edit".html_safe, edit_campaign_url(@campaign), :class => "btn" %>
3
+ <%= link_to "<i class='icon-home icon-white'></i>&nbsp;Home".html_safe, campaigns_url, :class => "btn btn-primary" %>
4
+ <h1>Campaign - <%= @campaign.name %>&nbsp;<small><abbr title="Append this to the end of each link used in this campaign e.g. http://yourdomain.com/?cid=1">?cid=<%= @campaign.id %></abbr></small></h1>
5
+ </div><!-- eo .page-header -->
4
6
 
5
7
  <section id="campaign-info">
6
- <p><strong>Campaign ID:</strong> <%= @campaign.id %></p>
7
-
8
- <p><strong>Campaign dates:</strong> From <%= @campaign.start_date.strftime("%d %B %Y") %> to <%= @campaign.end_date.strftime("%d %B %Y") %></p>
8
+ <% if @campaign.end_date < Date.today %>
9
+ <p class="ended">This campaign has ended.</p>
10
+ <% else %>
11
+ <p class="running">This campaign is currently running.</p>
12
+ <% end %>
9
13
  </section><!-- #campaign-info -->
10
14
 
11
15
  <section id="financials" class="stats">
12
- <h3><span class="financial-title">Campaign Spend:</span> $<%= sprintf("%.2f", @campaign.spend_amount) %></h3>
13
- <h3><span class="financial-title">Campaign Revenue:</span> $<%= sprintf("%.2f", @campaign.revenue) %></h3>
14
- <h3><span class="financial-title">Return on investment:</span> <%= sprintf("%.2f", @campaign.roi) %>%</h3>
16
+ <h3>Campaign Spend: <span>$<%= sprintf("%.2f", @campaign.spend_amount) %></span></h3>
17
+ <h3>Campaign Revenue: <span>$<%= sprintf("%.2f", @campaign.revenue) %></span></h3>
18
+ <h3>Return on investment: <span><%= sprintf("%.2f", @campaign.roi) %>%</span></h3>
15
19
  </section>
16
20
 
17
21
  <section id="visits" class="stats">
18
- <h3><span class="visit-title">Unique Campaign Visits:</span> <%= @campaign.visits %></h3>
19
- <h3><span class="visit-title">Conversion Rate:</span> <%= sprintf("%.2f",@campaign.conversion_rate) %>%</h3>
22
+ <h3>Unique Campaign Visits: <span><%= @campaign.visits %></span></h3>
23
+ <h3>Conversion Rate: <span><%= sprintf("%.2f",@campaign.conversion_rate) %>%</span></h3>
20
24
  </section>
21
25
 
22
26
  <h2>Signups via this campaign</h2>
23
27
 
24
- <table>
28
+ <table class="table table-striped">
25
29
  <thead>
26
30
  <tr>
27
31
  <th scope="col" width="25%">Name</th>
data/config/routes.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  Touchstone::Engine.routes.draw do
2
2
 
3
+ root :to => 'campaigns#index'
3
4
  resources :campaigns
4
5
 
5
6
  end
@@ -1,3 +1,7 @@
1
+ require 'rubygems'
2
+ require 'sass-rails'
3
+ require 'bootstrap-sass'
4
+
1
5
  module Touchstone
2
6
  class Engine < ::Rails::Engine
3
7
  isolate_namespace Touchstone
@@ -1,3 +1,3 @@
1
1
  module Touchstone
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: touchstone
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -27,6 +27,38 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '3.2'
30
+ - !ruby/object:Gem::Dependency
31
+ name: sass-rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '3.1'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '3.1'
46
+ - !ruby/object:Gem::Dependency
47
+ name: bootstrap-sass
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '2.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
30
62
  - !ruby/object:Gem::Dependency
31
63
  name: mysql2
32
64
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +85,7 @@ extra_rdoc_files: []
53
85
  files:
54
86
  - app/assets/javascripts/touchstone/application.js
55
87
  - app/assets/stylesheets/touchstone/application.css
56
- - app/assets/stylesheets/touchstone/touchstone.css
88
+ - app/assets/stylesheets/touchstone/touchstone.css.scss
57
89
  - app/controllers/touchstone/application_controller.rb
58
90
  - app/controllers/touchstone/campaigns_controller.rb
59
91
  - app/helpers/touchstone/application_helper.rb
@@ -62,6 +94,8 @@ files:
62
94
  - app/models/campaign_visit.rb
63
95
  - app/views/layouts/touchstone/application.html.erb
64
96
  - app/views/layouts/touchstone/touchstone.html.erb
97
+ - app/views/touchstone/campaigns/_campaign_form.html.erb
98
+ - app/views/touchstone/campaigns/edit.html.erb
65
99
  - app/views/touchstone/campaigns/index.html.erb
66
100
  - app/views/touchstone/campaigns/new.html.erb
67
101
  - app/views/touchstone/campaigns/show.html.erb
@@ -122,7 +156,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
156
  version: '0'
123
157
  segments:
124
158
  - 0
125
- hash: 1247631100298585288
159
+ hash: 2775789728872251427
126
160
  required_rubygems_version: !ruby/object:Gem::Requirement
127
161
  none: false
128
162
  requirements:
@@ -131,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
131
165
  version: '0'
132
166
  segments:
133
167
  - 0
134
- hash: 1247631100298585288
168
+ hash: 2775789728872251427
135
169
  requirements: []
136
170
  rubyforge_project:
137
171
  rubygems_version: 1.8.20
@@ -1,113 +0,0 @@
1
- .touchstone {
2
- font: 62.5% "Helvetica Neue", "Lucida Grande", "Trebuchet MS", Verdana, sans-serif;
3
- font-weight: normal;
4
- -webkit-text-shadow: 0px -1px 0px rgb(68,68,68);
5
- }
6
-
7
- .touchstone .wrapper {
8
- width: 960px;
9
- margin: 10px auto;
10
- }
11
-
12
- .touchstone h1 {
13
- font-size: 3em;
14
- margin-bottom: 1em;
15
- }
16
-
17
- .touchstone h2 {
18
- font-size: 2.4em;
19
- margin-bottom: 1em;
20
- }
21
-
22
- .touchstone h3 {
23
- font-size: 2em;
24
- margin-bottom: 1em;
25
- }
26
-
27
- .touchstone label {
28
- float: left;
29
- width: 120px;
30
- margin-top: 2px;
31
- font-weight: bold;
32
- }
33
-
34
- .touchstone p {
35
- font-size: 1.4em;
36
- margin-bottom: 1em;
37
- }
38
-
39
- .touchstone table {
40
- font-size: 1.4em;
41
- border: 1px solid rgb(153,178,183);
42
- border-spacing: 0px 0px;
43
- width: 100%;
44
- }
45
-
46
- .touchstone thead th {
47
- padding: 8px 5px;
48
- vertical-align: middle;
49
- text-align: left;
50
- text-transform: uppercase;
51
- border-bottom: 1px solid rgb(153,178,183);
52
- border-right: 1px solid rgb(153,178,183);
53
- background-color: rgb(213,222,217);
54
- }
55
-
56
- .touchstone td {
57
- font-size: 1.2em;
58
- padding: 5px;
59
- border-bottom: 1px solid rgb(153,178,183);
60
- border-right: 1px solid rgb(153,178,183);
61
- }
62
-
63
- .touchstone #new-campaign {
64
- float: right;
65
- margin-top: 10px;
66
- }
67
-
68
- .touchstone #flash_notice {
69
- background-color: #65ce6f;
70
- border: 1px solid #00cf13;
71
- font-weight: bold;
72
- text-align: center;
73
- padding: 5px 0;
74
- margin: 0 200px 10px 200px;
75
- }
76
-
77
- .touchstone #flash_error {
78
- background-color: #ff7272;
79
- border: 1px solid #ff1515;
80
- font-weight: bold;
81
- text-align: center;
82
- padding: 5px 0;
83
- margin: 0 200px 10px 200px;
84
- }
85
-
86
- .touchstone #campaign-info {
87
- margin: -3em 0 0 0;
88
- font-size: 0.8em;
89
- }
90
-
91
- .touchstone #campaign-info p {
92
- margin-top: -1em;
93
- }
94
-
95
- .touchstone #financials {
96
- margin-bottom: 10px;
97
- }
98
-
99
- .touchstone .stats h3 {
100
- display: inline;
101
- }
102
-
103
- .touchstone .stats span {
104
- color: rgb(153,178,183);
105
- }
106
-
107
- .touchstone .stats h3:not(:first-of-type) {
108
- margin-left: 15px;
109
- }
110
-
111
- .touchstone #visits {
112
- margin-bottom: 20px;
113
- }