plausible_api 0.1.2 → 0.1.8
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 +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +22 -1
- data/lib/plausible_api/client.rb +22 -3
- data/lib/plausible_api/stats/aggregate.rb +11 -12
- data/lib/plausible_api/stats/base.rb +84 -0
- data/lib/plausible_api/stats/breakdown.rb +20 -0
- data/lib/plausible_api/stats/realtime/visitors.rb +5 -4
- data/lib/plausible_api/stats/timeseries.rb +9 -10
- data/lib/plausible_api/version.rb +1 -1
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 725e6a56e5cee867b7d2440667a399d13c9310b37acb54a910cb7f26087273f3
         | 
| 4 | 
            +
              data.tar.gz: eea16b022039a10cf041030efab80f610ffe010a0adbbb561ceb9180ca6b9a81
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e760b16016faa8c19ec11698da4412d1432c36ab77569440cc4b532959c78489691ff238204c7e248973ce74a5d40aaaa54f7cfbfbaebaeb9e5cc28d7cebd438
         | 
| 7 | 
            +
              data.tar.gz: 2e0a07adcb710d4133e44dac5cd8fa783553b1f5a8733b106f031fe63ff7a9fa6b3e22af0fdeeec13880274405f99de1417e3baf297b22d5187e8ab7eb12c78c
         | 
    
        data/Gemfile.lock
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,4 +1,4 @@ | |
| 1 | 
            -
            # Plausible API  | 
| 1 | 
            +
            # Plausible API Ruby Gem
         | 
| 2 2 | 
             
            This is a simple wrapper to read the Plausible API with Ruby.
         | 
| 3 3 | 
             
            It's based on the WIP [API guide](https://plausible.io/docs/stats-api)
         | 
| 4 4 |  | 
| @@ -10,6 +10,10 @@ gem 'plausible_api' | |
| 10 10 | 
             
            Then you need to initialize a Client with your `site_id` (the domain) and your `token`.
         | 
| 11 11 | 
             
            ```rb
         | 
| 12 12 | 
             
            c = PlausibleApi::Client.new('dailytics.com', '123123') 
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            # Test if the site and token are valid
         | 
| 15 | 
            +
            c.valid?
         | 
| 16 | 
            +
            => true
         | 
| 13 17 | 
             
            ```
         | 
| 14 18 |  | 
| 15 19 | 
             
            ### Stats > Aggregate
         | 
| @@ -23,6 +27,7 @@ c.aggregate | |
| 23 27 | 
             
            c.aggregate({ period: '30d' })
         | 
| 24 28 | 
             
            c.aggregate({ period: '30d', metrics: 'visitors,pageviews' })
         | 
| 25 29 | 
             
            c.aggregate({ period: '30d', metrics: 'visitors,pageviews', filters: 'event:page==/order/confirmation' })
         | 
| 30 | 
            +
            c.aggregate({ date: '2021-01-01,2021-02-10' })
         | 
| 26 31 |  | 
| 27 32 | 
             
            # You'll get something like this:
         | 
| 28 33 | 
             
            => {"bounce_rate"=>{"value"=>81.0}, "pageviews"=>{"value"=>29}, "visit_duration"=>{"value"=>247.0}, "visitors"=>{"value"=>14}}
         | 
| @@ -38,11 +43,27 @@ c.timeseries | |
| 38 43 | 
             
            # Set parameters (period, filters, interval)
         | 
| 39 44 | 
             
            c.timeseries({ period: '7d' })
         | 
| 40 45 | 
             
            c.timeseries({ period: '7d', filters: 'event:page==/order/confirmation' })
         | 
| 46 | 
            +
            c.timeseries({ date: '2021-01-01,2021-02-15' })
         | 
| 41 47 |  | 
| 42 48 | 
             
            # You'll get something like this:
         | 
| 43 49 | 
             
            => [{"date"=>"2021-01-11", "value"=>100}, {"date"=>"2021-01-12", "value"=>120}, {"date"=>"2021-01-13", "value"=>80}...]
         | 
| 44 50 | 
             
            ```
         | 
| 45 51 |  | 
| 52 | 
            +
            ### Stats > Breakdown
         | 
| 53 | 
            +
            ```rb
         | 
| 54 | 
            +
            # Use the default parameters (30d, event:page)
         | 
| 55 | 
            +
            c.breakdown
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            # Set parameters (property, period, metrics, limit, page, filters, date)
         | 
| 58 | 
            +
            c.breakdown({ property: 'visit:source' })
         | 
| 59 | 
            +
            c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews' })
         | 
| 60 | 
            +
            c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews', period: '30d' })
         | 
| 61 | 
            +
            c.breakdown({ property: 'visit:source', metrics: 'visitors,pageviews', date: '2021-01-01,2021-02-01' })
         | 
| 62 | 
            +
             | 
| 63 | 
            +
            # You'll get something like this:
         | 
| 64 | 
            +
            => [{"page"=>"/", "visitors"=>41}, {"page"=>"/plans/", "visitors"=>14}, {"page"=>"/agencies/", "visitors"=>8}, {"page"=>"/features/", "visitors"=>8}, {"page"=>"/ready/", "visitors"=>5}, {"page"=>"/contact/", "visitors"=>4}, {"page"=>"/about/", "visitors"=>3}, {"page"=>"/donate/", "visitors"=>3}]
         | 
| 65 | 
            +
            ```
         | 
| 66 | 
            +
             | 
| 46 67 | 
             
            ### Realtime > Visitors
         | 
| 47 68 |  | 
| 48 69 | 
             
            It's as simple as:
         | 
    
        data/lib/plausible_api/client.rb
    CHANGED
    
    | @@ -1,8 +1,10 @@ | |
| 1 1 | 
             
            # frozen_string_literal: true
         | 
| 2 2 |  | 
| 3 | 
            +
            require 'plausible_api/stats/base'
         | 
| 3 4 | 
             
            require 'plausible_api/stats/realtime/visitors'
         | 
| 4 5 | 
             
            require 'plausible_api/stats/aggregate'
         | 
| 5 6 | 
             
            require 'plausible_api/stats/timeseries'
         | 
| 7 | 
            +
            require 'plausible_api/stats/breakdown'
         | 
| 6 8 |  | 
| 7 9 | 
             
            require 'json'
         | 
| 8 10 | 
             
            require "net/http"
         | 
| @@ -27,16 +29,27 @@ module PlausibleApi | |
| 27 29 | 
             
                  call PlausibleApi::Stats::Timeseries.new(options)
         | 
| 28 30 | 
             
                end
         | 
| 29 31 |  | 
| 32 | 
            +
                def breakdown(options = {})
         | 
| 33 | 
            +
                  call PlausibleApi::Stats::Breakdown.new(options)
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 30 36 | 
             
                def realtime_visitors
         | 
| 31 37 | 
             
                  call PlausibleApi::Stats::Realtime::Visitors.new
         | 
| 32 38 | 
             
                end
         | 
| 33 39 |  | 
| 34 | 
            -
                def  | 
| 35 | 
            -
                   | 
| 40 | 
            +
                def valid?
         | 
| 41 | 
            +
                  begin
         | 
| 42 | 
            +
                    realtime_visitors
         | 
| 43 | 
            +
                    return true
         | 
| 44 | 
            +
                  rescue
         | 
| 45 | 
            +
                    return false
         | 
| 46 | 
            +
                  end
         | 
| 36 47 | 
             
                end
         | 
| 37 48 |  | 
| 38 49 | 
             
                private
         | 
| 39 50 | 
             
                def call(api)      
         | 
| 51 | 
            +
                  raise StandardError.new api.errors unless api.valid?
         | 
| 52 | 
            +
                  
         | 
| 40 53 | 
             
                  url = "#{BASE_URL}#{api.request_url.gsub('$SITE_ID', @site_id)}"
         | 
| 41 54 | 
             
                  uri = URI.parse(url)
         | 
| 42 55 |  | 
| @@ -46,7 +59,13 @@ module PlausibleApi | |
| 46 59 | 
             
                  http = Net::HTTP.new(uri.host, uri.port)
         | 
| 47 60 | 
             
                  http.use_ssl = true  
         | 
| 48 61 |  | 
| 49 | 
            -
                   | 
| 62 | 
            +
                  response = http.request(req)
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                  if response.code == "200"
         | 
| 65 | 
            +
                    api.parse_response response.body
         | 
| 66 | 
            +
                  else
         | 
| 67 | 
            +
                    raise StandardError.new response.body
         | 
| 68 | 
            +
                  end
         | 
| 50 69 | 
             
                end
         | 
| 51 70 | 
             
              end
         | 
| 52 71 | 
             
            end
         | 
| @@ -2,21 +2,20 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module PlausibleApi
         | 
| 4 4 | 
             
              module Stats
         | 
| 5 | 
            -
                class Aggregate
         | 
| 5 | 
            +
                class Aggregate < Base
         | 
| 6 | 
            +
             | 
| 6 7 | 
             
                  def initialize(options = {})
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 8 | 
            +
                    super({ period: '30d', 
         | 
| 9 | 
            +
                            metrics: 'visitors,pageviews,bounce_rate,visit_duration' }
         | 
| 10 | 
            +
                          .merge(options))
         | 
| 11 | 
            +
                  end
         | 
| 12 | 
            +
                  
         | 
| 13 | 
            +
                  def request_url_base
         | 
| 14 | 
            +
                    "/api/v1/stats/aggregate?site_id=$SITE_ID"
         | 
| 11 15 | 
             
                  end
         | 
| 12 16 |  | 
| 13 | 
            -
                  def  | 
| 14 | 
            -
                     | 
| 15 | 
            -
                    url += "&period=#{@period}" if @period
         | 
| 16 | 
            -
                    url += "&metrics=#{@metrics}" if @metrics
         | 
| 17 | 
            -
                    url += "&filters=#{CGI.escape(@filters)}" if @filters
         | 
| 18 | 
            -
                    url += "&compare=#{@compare}" if @compare
         | 
| 19 | 
            -
                    url
         | 
| 17 | 
            +
                  def parse_response(body)
         | 
| 18 | 
            +
                    JSON.parse(body)['results']
         | 
| 20 19 | 
             
                  end
         | 
| 21 20 | 
             
                end
         | 
| 22 21 | 
             
              end
         | 
| @@ -0,0 +1,84 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module PlausibleApi
         | 
| 4 | 
            +
              module Stats
         | 
| 5 | 
            +
                class Base
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(options = {})
         | 
| 8 | 
            +
                    @options = { compare: nil, date: nil, filters: nil, interval: nil,
         | 
| 9 | 
            +
                                  limit: nil, metrics: nil, page: nil, period: nil, 
         | 
| 10 | 
            +
                                  property: nil }.merge(options)
         | 
| 11 | 
            +
                    @options[:period] = 'custom' if @options[:date]
         | 
| 12 | 
            +
                  end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def request_url_base
         | 
| 15 | 
            +
                    raise NotImplementedError
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def request_url
         | 
| 19 | 
            +
                    params = @options.select{ |_,v| !v.to_s.empty? }
         | 
| 20 | 
            +
                    [request_url_base, URI.encode_www_form(params)].reject{|e| e.empty?}.join('&')
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  def parse_response(body)
         | 
| 24 | 
            +
                    raise NotImplementedError
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  def valid?
         | 
| 28 | 
            +
                    errors.empty?
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  def errors  
         | 
| 32 | 
            +
                    allowed_period   = %w(12mo 6mo month 30d 7d day custom)
         | 
| 33 | 
            +
                    allowed_metrics  = %w(visitors pageviews bounce_rate visit_duration)
         | 
| 34 | 
            +
                    allowed_compare  = %w(previous_period)
         | 
| 35 | 
            +
                    allowed_interval = %w(date month)
         | 
| 36 | 
            +
                    allowed_property = %w(event:page visit:source visit:referrer visit:utm_medium 
         | 
| 37 | 
            +
                      visit:utm_source visit:utm_campaign visit:device visit:browser visit:browser_version 
         | 
| 38 | 
            +
                      visit:os visit:os_version visit:country)
         | 
| 39 | 
            +
                    e = 'Not a valid parameter. Allowed parameters are: '
         | 
| 40 | 
            +
                    
         | 
| 41 | 
            +
                    errors = []
         | 
| 42 | 
            +
                    if @options[:period]
         | 
| 43 | 
            +
                      errors.push({ period: "#{e}#{allowed_period.join(', ')}" }) unless allowed_period.include? @options[:period]
         | 
| 44 | 
            +
                    end
         | 
| 45 | 
            +
                    if @options[:metrics]
         | 
| 46 | 
            +
                      metrics_array = @options[:metrics].split(',') 
         | 
| 47 | 
            +
                      errors.push({ metrics: "#{e}#{allowed_metrics.join(', ')}" }) unless metrics_array & allowed_metrics == metrics_array
         | 
| 48 | 
            +
                    end
         | 
| 49 | 
            +
                    if @options[:compare]
         | 
| 50 | 
            +
                      errors.push({ compare: "#{e}#{allowed_compare.join(', ')}" }) unless allowed_compare.include? @options[:compare]
         | 
| 51 | 
            +
                    end
         | 
| 52 | 
            +
                    if @options[:interval]
         | 
| 53 | 
            +
                      errors.push({ interval: "#{e}#{allowed_interval.join(', ')}" }) unless allowed_interval.include? @options[:interval]
         | 
| 54 | 
            +
                    end
         | 
| 55 | 
            +
                    if @options[:property]
         | 
| 56 | 
            +
                      errors.push({ property: "#{e}#{allowed_property.join(', ')}" }) unless allowed_property.include? @options[:property]
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                    if @options[:filters]
         | 
| 59 | 
            +
                      filters_array = @options[:filters].to_s.split(';')
         | 
| 60 | 
            +
                      filters_array.each do |f|
         | 
| 61 | 
            +
                        parts = f.split("==")
         | 
| 62 | 
            +
                        errors.push({ filters: "Unrecognized filter: #{f}" }) unless parts.length == 2
         | 
| 63 | 
            +
                        errors.push({ filters: "Unknown metric for filter: #{parts[0]}" }) unless allowed_property.include? parts[0]
         | 
| 64 | 
            +
                      end
         | 
| 65 | 
            +
                    end
         | 
| 66 | 
            +
                    if @options[:limit]
         | 
| 67 | 
            +
                      errors.push({ limit: "Limit param must be a positive number" }) unless @options[:limit].is_a? Integer and @options[:limit] > 0
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
                    if @options[:page]
         | 
| 70 | 
            +
                      errors.push({ page: "Page param must be a positive number" }) unless @options[:page].is_a? Integer and @options[:page] > 0
         | 
| 71 | 
            +
                    end
         | 
| 72 | 
            +
                    if @options[:date]
         | 
| 73 | 
            +
                      errors.push({ date: 'You must define the period parameter as custom' }) unless @options[:period] == 'custom'
         | 
| 74 | 
            +
                      date_array = @options[:date].split(",")
         | 
| 75 | 
            +
                      errors.push({ date: 'You must define start and end dates divided by comma' }) unless date_array.length == 2
         | 
| 76 | 
            +
                      regex = /\d{4}\-\d{2}\-\d{2}/
         | 
| 77 | 
            +
                      errors.push({ date: 'Wrong format for the start date' }) unless date_array[0] =~ regex
         | 
| 78 | 
            +
                      errors.push({ date: 'Wrong format for the end date' }) unless date_array[1] =~ regex
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                    errors
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module PlausibleApi
         | 
| 4 | 
            +
              module Stats
         | 
| 5 | 
            +
                class Breakdown < Base
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                  def initialize(options = {})
         | 
| 8 | 
            +
                    super({ period: '30d', property: 'event:page' }.merge(options))
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  
         | 
| 11 | 
            +
                  def request_url_base
         | 
| 12 | 
            +
                    "/api/v1/stats/breakdown?site_id=$SITE_ID"
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def parse_response(body)
         | 
| 16 | 
            +
                    JSON.parse(body)['results']
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -3,12 +3,13 @@ | |
| 3 3 | 
             
            module PlausibleApi 
         | 
| 4 4 | 
             
              module Stats
         | 
| 5 5 | 
             
                module Realtime
         | 
| 6 | 
            -
                  class Visitors
         | 
| 7 | 
            -
                    def  | 
| 6 | 
            +
                  class Visitors < PlausibleApi::Stats::Base
         | 
| 7 | 
            +
                    def request_url_base
         | 
| 8 | 
            +
                      "/api/v1/stats/realtime/visitors?site_id=$SITE_ID"
         | 
| 8 9 | 
             
                    end
         | 
| 9 10 |  | 
| 10 | 
            -
                    def  | 
| 11 | 
            -
                       | 
| 11 | 
            +
                    def parse_response(body)
         | 
| 12 | 
            +
                      body.to_i
         | 
| 12 13 | 
             
                    end
         | 
| 13 14 | 
             
                  end
         | 
| 14 15 | 
             
                end
         | 
| @@ -2,19 +2,18 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module PlausibleApi
         | 
| 4 4 | 
             
              module Stats
         | 
| 5 | 
            -
                class Timeseries
         | 
| 5 | 
            +
                class Timeseries < Base
         | 
| 6 | 
            +
             | 
| 6 7 | 
             
                  def initialize(options = {})
         | 
| 7 | 
            -
                     | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 8 | 
            +
                    super({ period: '30d' }.merge(options))
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                  
         | 
| 11 | 
            +
                  def request_url_base
         | 
| 12 | 
            +
                    "/api/v1/stats/timeseries?site_id=$SITE_ID"
         | 
| 10 13 | 
             
                  end
         | 
| 11 14 |  | 
| 12 | 
            -
                  def  | 
| 13 | 
            -
                     | 
| 14 | 
            -
                    url += "&period=#{@period}" if @period
         | 
| 15 | 
            -
                    url += "&filters=#{CGI.escape(@filters)}" if @filters
         | 
| 16 | 
            -
                    url += "&interval=#{@interval}" if @interval
         | 
| 17 | 
            -
                    url
         | 
| 15 | 
            +
                  def parse_response(body)
         | 
| 16 | 
            +
                    JSON.parse(body)['results']
         | 
| 18 17 | 
             
                  end
         | 
| 19 18 | 
             
                end
         | 
| 20 19 | 
             
              end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: plausible_api
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.8
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Gustavo Garcia
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021- | 
| 11 | 
            +
            date: 2021-03-23 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies: []
         | 
| 13 13 | 
             
            description: A very humble wrapper for the new API by Plausible
         | 
| 14 14 | 
             
            email:
         | 
| @@ -29,6 +29,8 @@ files: | |
| 29 29 | 
             
            - lib/plausible_api.rb
         | 
| 30 30 | 
             
            - lib/plausible_api/client.rb
         | 
| 31 31 | 
             
            - lib/plausible_api/stats/aggregate.rb
         | 
| 32 | 
            +
            - lib/plausible_api/stats/base.rb
         | 
| 33 | 
            +
            - lib/plausible_api/stats/breakdown.rb
         | 
| 32 34 | 
             
            - lib/plausible_api/stats/realtime/visitors.rb
         | 
| 33 35 | 
             
            - lib/plausible_api/stats/timeseries.rb
         | 
| 34 36 | 
             
            - lib/plausible_api/version.rb
         |