spree_piwik 0.0.1
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.
- checksums.yaml +15 -0
- data/.gitignore +14 -0
- data/.hound.yml +2 -0
- data/.rspec +1 -0
- data/.travis.yml +4 -0
- data/Gemfile +7 -0
- data/README.md +41 -0
- data/Rakefile +21 -0
- data/app/assets/javascripts/spree/backend/spree_piwik.js +2 -0
- data/app/assets/javascripts/spree/frontend/spree_piwik.js +2 -0
- data/app/assets/stylesheets/spree/backend/spree_piwik.css +4 -0
- data/app/assets/stylesheets/spree/frontend/spree_piwik.css +4 -0
- data/app/helpers/spree/base_helper_decorator.rb +5 -0
- data/app/models/spree/piwik/client.rb +29 -0
- data/app/models/spree/piwik/line_item.rb +44 -0
- data/app/models/spree/piwik_configuration.rb +4 -0
- data/app/overrides/add_piwik_tracking_tag_to_layout.rb +5 -0
- data/app/views/spree/_ecommerce_item.html.erb +7 -0
- data/app/views/spree/_ecommerce_view.html.erb +6 -0
- data/app/views/spree/_piwik.html.erb +19 -0
- data/bin/rails +7 -0
- data/config/.jshint.json +3 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +3 -0
- data/config/spring.rb +1 -0
- data/lib/generators/spree_piwik/install/install_generator.rb +32 -0
- data/lib/spree/piwik/engine.rb +32 -0
- data/lib/spree_piwik.rb +2 -0
- data/spec/features/interact_with_cart_spec.rb +49 -0
- data/spec/features/visit_home_pages_spec.rb +21 -0
- data/spec/features/visit_product_page_spec.rb +45 -0
- data/spec/fixtures/empty_cart.js +9 -0
- data/spec/fixtures/index_example_com.js +8 -0
- data/spec/fixtures/multiple_products_in_cart.js +23 -0
- data/spec/fixtures/one_product_in_cart.js +16 -0
- data/spec/fixtures/product_example_com.js +14 -0
- data/spec/fixtures/product_with_categories.js +14 -0
- data/spec/helpers/spree/base_helper_decorator_spec.rb +35 -0
- data/spec/models/spree/piwik/client_spec.rb +71 -0
- data/spec/models/spree/piwik/line_item_spec.rb +59 -0
- data/spec/models/spree/piwik_configuration_spec.rb +11 -0
- data/spec/overrides/add_piwik_tracking_tag_to_layout_spec.rb +20 -0
- data/spec/spec_helper.rb +96 -0
- data/spec/support/components/piwig_tag_component.rb +37 -0
- data/spec/support/helpers/fixture_helpers.rb +11 -0
- data/spree_piwik.gemspec +35 -0
- metadata +370 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MmM0NWQ2NmY5ZTQ5YmUzZjU0MzViYzYxYzA4ZTZlMWY3Nzc4MWQxMA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
MjI0OWI2ZTJiZWNjNGFiZjE3ZGI3M2ZkNWY4NzZjOGM0ODVhNGJjOQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZDg4MmJmZjI2ZDQyNmVkNmRmMDVjMDFhMjJjNjk0MzAzNTliNTFkYjY4Yjgx
|
10
|
+
NzYyOWEzMzNkMTYzYWRkNWNiZGM5N2QwMThhNzJlYzg2OTkwYWMxNjVkZDQz
|
11
|
+
MzliZjI3Mzg4MGRmODIxNjVmMjFlZTdiN2M5ZTFiODY0MjQzYWI=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YmZlYTBiNGRjYzM3OTBlY2ZjOTVkMWU1MTRmYmI0NzE3MDVmNDJkNzJlZmQx
|
14
|
+
M2EwOWVlMjljNThhZmNkMWNkODc4ZWI1YTU2MWI4OGZjNTMzZGQ3OGQwYTk1
|
15
|
+
ZDJhOTRkMDQwOGU4OTUxODBmNGMwM2MwNjE0ZWU3ZDc3NTA1ZDM=
|
data/.gitignore
ADDED
data/.hound.yml
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
SpreePiwik
|
2
|
+
==========
|
3
|
+
|
4
|
+
Adds piwik tracking with Ecommerce tracking
|
5
|
+
|
6
|
+
Status
|
7
|
+
------
|
8
|
+
|
9
|
+
[](https://travis-ci.org/berkes/spree_piwik)
|
10
|
+
[](https://codeclimate.com/github/berkes/spree_piwik)
|
11
|
+
|
12
|
+
Installation
|
13
|
+
------------
|
14
|
+
|
15
|
+
Add spree_piwik to your Gemfile:
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
gem 'spree_piwik'
|
19
|
+
```
|
20
|
+
|
21
|
+
Bundle your dependencies and run the installation generator:
|
22
|
+
|
23
|
+
```shell
|
24
|
+
bundle
|
25
|
+
bundle exec rails g spree_piwik:install
|
26
|
+
```
|
27
|
+
|
28
|
+
Testing
|
29
|
+
-------
|
30
|
+
|
31
|
+
First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
|
32
|
+
|
33
|
+
```shell
|
34
|
+
bundle
|
35
|
+
bundle exec rake
|
36
|
+
```
|
37
|
+
|
38
|
+
When testing your applications integration with this extension you may use it's factories.
|
39
|
+
Simply add this require statement to your spec_helper:
|
40
|
+
|
41
|
+
Copyright (c) 2015 Bèr Kessels
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
require 'spree/testing_support/extension_rake'
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new
|
8
|
+
|
9
|
+
task :default do
|
10
|
+
if Dir["spec/dummy"].empty?
|
11
|
+
Rake::Task[:test_app].invoke
|
12
|
+
Dir.chdir("../../")
|
13
|
+
end
|
14
|
+
Rake::Task[:spec].invoke
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generates a dummy app for testing'
|
18
|
+
task :test_app do
|
19
|
+
ENV['LIB_NAME'] = 'spree_piwik'
|
20
|
+
Rake::Task['extension:test_app'].invoke
|
21
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Spree
|
2
|
+
module Piwik
|
3
|
+
class Client
|
4
|
+
include ActiveModel::Model
|
5
|
+
|
6
|
+
attr_accessor :product, :order
|
7
|
+
|
8
|
+
def product
|
9
|
+
Spree::Piwik::LineItem.from_product_ish(@product) if @product
|
10
|
+
end
|
11
|
+
|
12
|
+
def url
|
13
|
+
Spree::Piwik::Config.preferred_piwik_url
|
14
|
+
end
|
15
|
+
|
16
|
+
def site_id
|
17
|
+
Spree::Piwik::Config.preferred_piwik_id
|
18
|
+
end
|
19
|
+
|
20
|
+
def ecommerce_items
|
21
|
+
@order.line_items.map { |li| LineItem.from_product_ish(li) }
|
22
|
+
end
|
23
|
+
|
24
|
+
def track_cart_update?
|
25
|
+
!@order.nil? && @order.cart?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Spree
|
2
|
+
module Piwik
|
3
|
+
class LineItem
|
4
|
+
include ActiveModel::Model
|
5
|
+
|
6
|
+
ATTRIBUTES = [:sku, :name, :price, :quantity, :categories]
|
7
|
+
attr_accessor(*ATTRIBUTES)
|
8
|
+
|
9
|
+
##
|
10
|
+
# Create a LineItem from a Spree::LinteItem-ish thing (line_items,
|
11
|
+
# products, variants)
|
12
|
+
#
|
13
|
+
# All attributes in ATTRIBUTES will be mapped:
|
14
|
+
#
|
15
|
+
# When we add a (private) method with the name
|
16
|
+
# map_product_ish_sku, this method will be called and get the
|
17
|
+
# product_ish to generate a value for that attribute.
|
18
|
+
#
|
19
|
+
# When the product_ish has the same attribute name and no
|
20
|
+
# mapping-method provided the value, it will simply use the value
|
21
|
+
# from that attribute on product_ish
|
22
|
+
def self.from_product_ish(product_ish)
|
23
|
+
values = ATTRIBUTES.map { |a| [a, product_ish_attr(a, product_ish)] }
|
24
|
+
new(Hash[values])
|
25
|
+
end
|
26
|
+
|
27
|
+
# Private
|
28
|
+
def self.product_ish_attr(attr_name, product_ish)
|
29
|
+
mapping_method = "map_product_ish_#{attr_name}".to_sym
|
30
|
+
if respond_to?(mapping_method)
|
31
|
+
send(mapping_method, product_ish)
|
32
|
+
else
|
33
|
+
product_ish.try(attr_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Private
|
38
|
+
def self.map_product_ish_categories(product_ish)
|
39
|
+
defaulted_taxons = product_ish.try(:taxons) || []
|
40
|
+
defaulted_taxons.map(&:name).first(5)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<!-- Piwik -->
|
2
|
+
<script type="text/javascript">
|
3
|
+
var _paq = _paq || [];
|
4
|
+
(function(){ var u=(('https:' == document.location.protocol) ? 'https://<%= piwik_client.url %>/' : 'http://<%= piwik_client.url %>/');
|
5
|
+
_paq.push(['setSiteId', <%= piwik_client.site_id %>]);
|
6
|
+
_paq.push(['setTrackerUrl', u+'piwik.php']);
|
7
|
+
<%- if piwik_client.product %>
|
8
|
+
<%= render partial: 'spree/ecommerce_view', locals: { product: piwik_client.product } %>
|
9
|
+
<% end %>
|
10
|
+
<% if piwik_client.track_cart_update? %>
|
11
|
+
<%= render :partial => 'spree/ecommerce_item', :collection => piwik_client.ecommerce_items %>
|
12
|
+
_paq.push(['trackEcommerceCartUpdate', <%= piwik_client.order.total %>]);
|
13
|
+
<% end %>
|
14
|
+
_paq.push(['trackPageView']);
|
15
|
+
_paq.push(['enableLinkTracking']);
|
16
|
+
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'piwik.js';
|
17
|
+
s.parentNode.insertBefore(g,s); })();
|
18
|
+
</script>
|
19
|
+
<!-- End Piwik Code -->
|
data/bin/rails
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
|
2
|
+
|
3
|
+
ENGINE_ROOT = File.expand_path('../..', __FILE__)
|
4
|
+
ENGINE_PATH = File.expand_path('../../lib/spree_piwik/engine', __FILE__)
|
5
|
+
|
6
|
+
require 'rails/all'
|
7
|
+
require 'rails/engine/commands'
|
data/config/.jshint.json
ADDED
data/config/routes.rb
ADDED
data/config/spring.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Spring.application_root = File.join('spec', 'dummy')
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# Must be named SpreePiwik because dummygenerator expects it
|
2
|
+
module SpreePiwik
|
3
|
+
module Generators
|
4
|
+
class InstallGenerator < Rails::Generators::Base
|
5
|
+
|
6
|
+
class_option :auto_run_migrations, :type => :boolean, :default => false
|
7
|
+
|
8
|
+
def add_javascripts
|
9
|
+
append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/spree_piwik\n"
|
10
|
+
append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/spree_piwik\n"
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_stylesheets
|
14
|
+
inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/spree_piwik\n", :before => /\*\//, :verbose => true
|
15
|
+
inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/spree_piwik\n", :before => /\*\//, :verbose => true
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_migrations
|
19
|
+
run 'bundle exec rake railties:install:migrations FROM=spree_piwik'
|
20
|
+
end
|
21
|
+
|
22
|
+
def run_migrations
|
23
|
+
run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
|
24
|
+
if run_migrations
|
25
|
+
run 'bundle exec rake db:migrate'
|
26
|
+
else
|
27
|
+
puts 'Skipping rake db:migrate, don\'t forget to run it!'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Spree
|
2
|
+
module Piwik
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
module Spree
|
8
|
+
module Piwik
|
9
|
+
class Engine < Rails::Engine
|
10
|
+
require 'spree/core'
|
11
|
+
isolate_namespace Spree
|
12
|
+
engine_name 'spree_piwik'
|
13
|
+
|
14
|
+
# use rspec for tests
|
15
|
+
config.generators do |g|
|
16
|
+
g.test_framework :rspec
|
17
|
+
end
|
18
|
+
|
19
|
+
initializer 'spree.piwik.environment', :before => :load_config_initializers do |app|
|
20
|
+
Spree::Piwik::Config = Spree::PiwikConfiguration.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.activate
|
24
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../../app/**/*_decorator*.rb')) do |c|
|
25
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
config.to_prepare &method(:activate).to_proc
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/spree_piwik.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "InteractWithCart", type: :feature do
|
4
|
+
scenario "An anonymous user adds a product to the cart" do
|
5
|
+
@product = create(:product, sku: "SKU-1", name: "RoR Shirt")
|
6
|
+
visit "products/#{@product.slug}"
|
7
|
+
click_button "Add To Cart"
|
8
|
+
|
9
|
+
tag_component = PiwikTagComponent.new
|
10
|
+
expect(tag_component.as_ecma).to eq fixture("one_product_in_cart.js")
|
11
|
+
end
|
12
|
+
|
13
|
+
scenario "An anonymous user adds multiple products to the cart" do
|
14
|
+
@shirt = create(:product, sku: "SKU-1", name: "RoR Shirt")
|
15
|
+
visit "products/#{@shirt.slug}"
|
16
|
+
click_button "Add To Cart"
|
17
|
+
@sticker = create(:product, sku: "SKU-2", name: "RoR Sticker", price: 0.99)
|
18
|
+
visit "products/#{@sticker.slug}"
|
19
|
+
click_button "Add To Cart"
|
20
|
+
|
21
|
+
tag_component = PiwikTagComponent.new
|
22
|
+
expect(tag_component.as_ecma).to eq fixture("multiple_products_in_cart.js")
|
23
|
+
end
|
24
|
+
|
25
|
+
scenario "An anonymous user removes a product from cart" do
|
26
|
+
@shirt = create(:product, sku: "SKU-1", name: "RoR Shirt")
|
27
|
+
visit "products/#{@shirt.slug}"
|
28
|
+
click_button "Add To Cart"
|
29
|
+
@sticker = create(:product, sku: "SKU-2", name: "RoR Sticker", price: 0.99)
|
30
|
+
visit "products/#{@sticker.slug}"
|
31
|
+
click_button "Add To Cart"
|
32
|
+
|
33
|
+
fill_in(:order_line_items_attributes_1_quantity, with: 0)
|
34
|
+
click_button "Update"
|
35
|
+
|
36
|
+
tag_component = PiwikTagComponent.new
|
37
|
+
expect(tag_component.as_ecma).to eq fixture("one_product_in_cart.js")
|
38
|
+
end
|
39
|
+
|
40
|
+
scenario "An anonymous user empties a cart" do
|
41
|
+
@shirt = create(:product, sku: "SKU-1", name: "RoR Shirt")
|
42
|
+
visit "products/#{@shirt.slug}"
|
43
|
+
click_button "Add To Cart"
|
44
|
+
click_button "Empty Cart"
|
45
|
+
|
46
|
+
tag_component = PiwikTagComponent.new
|
47
|
+
expect(tag_component.as_ecma).to eq fixture("empty_cart.js")
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "TrackingTagForIndex", type: :feature do
|
4
|
+
before do
|
5
|
+
# User has set piwik_url and piwik_id
|
6
|
+
Spree::Piwik::Config.set(piwik_url: "piwik.example.com")
|
7
|
+
Spree::Piwik::Config.set(piwik_id: 1337)
|
8
|
+
end
|
9
|
+
|
10
|
+
scenario "An anonymous user is tracked on the home page" do
|
11
|
+
visit "/"
|
12
|
+
|
13
|
+
# Sanity check
|
14
|
+
expect(page).to have_content "Powered by Spree"
|
15
|
+
|
16
|
+
tag_component = PiwikTagComponent.new
|
17
|
+
expect(tag_component).to be_in_html
|
18
|
+
expect(tag_component.tracker_url_assigment).to include("piwik.example.com")
|
19
|
+
expect(tag_component.as_ecma).to eq fixture("index_example_com.js")
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
feature "TrackingTagForProduct", type: :feature do
|
4
|
+
# As a shop-owner
|
5
|
+
# I want to send stats with the product"s attributes to piwik
|
6
|
+
# So that I can allow Piwik to process reports on SKU and products.
|
7
|
+
scenario "An anonymous user is tracked on a product page" do
|
8
|
+
@product = create(:product, sku: "SKU-1", name: "RoR Shirt")
|
9
|
+
# TODO replace with visit "product/slug"
|
10
|
+
visit "/"
|
11
|
+
click_link(@product.name)
|
12
|
+
|
13
|
+
# Sanity check
|
14
|
+
expect(page).to have_content @product.name
|
15
|
+
|
16
|
+
tag_component = PiwikTagComponent.new
|
17
|
+
expect(tag_component).to be_in_html
|
18
|
+
expect(tag_component.to_s).to include "setEcommerceView"
|
19
|
+
expect(tag_component.as_ecma).to eq fixture("product_example_com.js")
|
20
|
+
end
|
21
|
+
|
22
|
+
# As a shop-owner
|
23
|
+
# I want to send the categories in a product to piwik
|
24
|
+
# So that can filter stats in Piwik on categories
|
25
|
+
scenario "An anonymous user is tracked on a product page with categories" do
|
26
|
+
taxons = [
|
27
|
+
create(:taxon, name: "shirts"),
|
28
|
+
create(:taxon, name: "ror"),
|
29
|
+
create(:taxon, name: "webdev"),
|
30
|
+
]
|
31
|
+
@product = create(:product, sku: "SKU-1", name: "RoR Shirt", taxons: taxons)
|
32
|
+
|
33
|
+
# TODO replace with visit "product/slug"
|
34
|
+
visit "/"
|
35
|
+
click_link(@product.name)
|
36
|
+
|
37
|
+
# Sanity check
|
38
|
+
expect(page).to have_content @product.name
|
39
|
+
|
40
|
+
tag_component = PiwikTagComponent.new
|
41
|
+
expect(tag_component).to be_in_html
|
42
|
+
expect(tag_component.to_s).to include "setEcommerceView"
|
43
|
+
expect(tag_component.as_ecma).to eq fixture("product_with_categories.js")
|
44
|
+
end
|
45
|
+
end
|