spree_piwik 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/berkes/spree_piwik.svg?branch=develop)](https://travis-ci.org/berkes/spree_piwik)
|
10
|
+
[![Code Climate](https://codeclimate.com/github/berkes/spree_piwik/badges/gpa.svg)](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
|