Question

I have written a Jekyll plugin to display the number of pageviews on a page by calling the Google Analytics API using the garb gem. The only trouble with my approach is that it makes a call to the API for each page, slowing down build time and also potentially hitting the user call limits on the API.

It would be possible to return all the data in a single call and store it locally, and then look up the pageview count from each page, but my Jekyll/Ruby-fu isn't up to scratch. I do not know how to write the plugin to run once to get all the data and store it locally where my current function could then access it, rather than calling the API page by page.

Basically my code is written as a liquid block that can be put into my page layout:

 class GoogleAnalytics < Liquid::Block
    def initialize(tag_name, markup, tokens)
      super # options that appear in block (between tag and endtag)
      @options = markup # optional optionss passed in by opening tag
    end
    def render(context)
      path = super
      # Read in credentials and authenticate 
      cred = YAML.load_file("/home/cboettig/.garb_auth.yaml")
      Garb::Session.api_key = cred[:api_key]
      token = Garb::Session.login(cred[:username], cred[:password])
      profile = Garb::Management::Profile.all.detect {|p| p.web_property_id == cred[:ua]}

      # place query, customize to modify results
      data = Exits.results(profile, 
                           :filters => {:page_path.eql => path}, 
                           :start_date => Chronic.parse("2011-01-01"))

      data.first.pageviews
    end

Full version of my plugin is here

How can I move all the calls to the API to some other function and make sure jekyll runs that once at the start, and then adjust the tag above to read that local data?

EDIT Looks like this can be done with a Generator and writing the data to a file. See example on this branch Now I just need to figure out how to subset the results: https://github.com/Sija/garb/issues/22

Was it helpful?

Solution

To store the data, I had to:

  1. Write a Generator class (see Jekyll wiki plugins) to call the API.

  2. Convert data to a hash (for easy lookup by path, see 5):

    result = Hash[data.collect{|row| [row.page_path, [row.exits, row.pageviews]]}]
    
  3. Write the data hash to a JSON file.

  4. Read in the data from the file in my existing Liquid block class.

    Note that the block tag works from the _includes dir, while the generator works from the root directory.

  5. Match the page path, easy once the data is converted to a hash:

    result[path][1]
    

Code for the full plugin, showing how to create the generator and write files, etc, here

And thanks to Sija on GitHub for help on this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top