coaching newsletter contact

From WordPress and Google to Jekyll and Piwik

This website has run on WordPress and Google Analytics from day one and they've both treated me pretty well. But I've started to see a need for more flexibility in the site, so it's time for a big change.

This is mostly a back-end change that shouldn't affect the UI much. There are a few small UI changes I'm making, but that's to make the site cleaner. The more I've gotten into web development and design the pickier I've become with my site. Ultimately, I'm looking for a simplified user experience for you and more respect for your privacy.

Why WordPress and Google?

For about a year and a half I ran the site on WordPress through Bluehost with Google Analytics. It was easy and quick for me at the time. WordPress has a good, long track record so I fell in line to get my site up quickly. I didn't want to worry about technicalities - I needed to spend my time creating.

The standard for analytics has been Google Analytics for some time. Google has a reputation for having some of the best if not the best reports and tracking for your website. When I started I knew very little about tracking. I was just looking for a way to see what kind of traffic I was getting and almost everyone recommended GA. Sometimes I'm okay with taking the easy road if it means shipping something quickly. I can evaluate the nuances later. And I can always do the research and migration process after the launch if I need to - which is what I've done here.

Why Jekyll?

As a replacement for WordPress, I've decided to create a static site using Jekyll. I ran across Jekyll through blog posts from Brett Terpstra. I then spent a couple of hours researching and reviewing websites built with Jekyll. I was blown away by the load speeds involved.

I started looking at some of the numbers on my site and found that the average page was loading in about eight seconds. All of the tests I was doing on my machine came in around four seconds, but that didn't take into account the various devices that people use. That extra four seconds meant my site was way too slow. Eight seconds? Sites built with Jekyll are typically loading in less than one second.

I've been wanting to get into Ruby and Rails lately. Since Jekyll is built on Ruby and I learn by using a language, it made for a good project. Jekyll seems to be one of the most common static site generators as well. There's a lot of support and plugins for it already, so I felt comfortable joining that community.

Moving to a static site allows me the flexibility to build one-off pages and posts in a highly customized way. Since I'm becoming more particular about how things look and how you interact with them, it only makes sense. Jekyll seems to fit the bill quite well.

Why Piwik?

I want to step away from the data collection that Google does on you. I don't want to share your data against your will and I don't want to put you into their system simply because you wanted to read my articles. I understand that you might be okay with this, but I'm learning that I'm not necessarily okay with this myself. There's a big backlash against ads and tracking right now and although I'm not wanting to jump on that bandwagon, it is something that I've been thinking a lot about lately.

And although tracking and ads are okay in some scenarios, I've found that I'm uneasy about the tracking that goes alongside Google Analytics. That might be unwarranted and unfounded, but I don't want to leave it when it makes me uncomfortable. A great example of this is Marco Arment and his ad-blocking iOS app. He had a great app and it worked well, but it didn't feel right for him. So he pulled it and Apple issued refunds. Google Analytics on this website falls in the same category for me. It might be okay, but I'm not comfortable with it.

I still have a need to understand the analytics for my site so I started looking for alternatives and ran across Piwik. It allows me to collect the numbers that I'm looking for, but the data stays local. There is no master server that the numbers go back to. Your data never leaves the site. I have a database (that only I have access to) that stores the information and it sits on the same server that this website sits on. The data is anonymous and never goes anywhere. It allows me to get those numbers and not sacrifice your privacy in the process. I think that's a great trade-off.

Hosting?

In the process of making the shift to a static site, I'm also launching a new sub-domain that will be running on Rails. I was previously running my hosting through Bluehost, but while setting up a Rails application, I found that Bluehost is not very easy to use for anything other than one-click installations. So I'm also moving my host over to Digital Ocean (affiliate).

When?

Today. I spent the last few weeks working on the static site. There are still some bugs I'm working out, but for the most part it's all here. Let me know what you think!

Thu, Oct 15, 2015 07:00pm CDT https://bhlg.us/4di8
#development #jekyll #piwik

Other mentions

Joe Buhlig

When I switched this blog to Jekyll, one of the features I lost was the ability to schedule posts for the future. Yes, Jekyll can handle future dates on posts, but you still need to run a command to build the site and the deploy it to you web server.

And I have been operating without that ability for over four years now. But this past December I decided to be done with manually posting articles and setting aside time to do the deployment by hand. So I set about building the following structure to allow me to publish new articles and microblogs to the site.

build.sh

jekyll-repo/build.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

cd /path/to/repo/

. /home/username/.bashrc

git fetch origin master --quiet
mycommit=$(git rev-parse HEAD)
origincommit=$(git rev-parse origin/master)
if [ "$mycommit" = "$origincommit" ]
then
  bundle exec rake publish
else
  git reset --hard origin/master
  git pull
  bundle install > /dev/null
  bundle exec rake build
  bundle exec whenever --update-cron
fi

This all starts with a build script. It sits at the top-level of the repo: my-repo/build.sh. All this does is check for new git commits. If no new commits exist, it runs a rake task to see if there are any new posts or microblogs available. More on that later.

If it does find a new commit, there are a few steps it takes. First, it resets the local repository, pulls the new commit, and then runs a bundle install. This allows me to update the Gemfile and add any dependencies I may need without logging into the web server and updating it.

Then it runs the build task. Again, more on that below. But after the build task, it runs the whenever command to update my cron tasks, which begs the question: what cron tasks?

Cron Job

I added gem whenever to my Gemfile and then put this in config/schedule.rb:

jekyll-repo/config/schedule.rb
1
2
3
4
5
set :output, "/path/to/log/my.log"

every 5.minutes do
 command "sh /path/to/repo/build.sh"
end

By using the whenever gem, I can update the server cron job(s) by simply committing the changes to the repo. The build script will pull the changes and run the command to update the cron job.

At this point, I hope you can see the beauty of this. The build.sh script is run via cron job every five minutes. And that script updates the cron job. They keep each other current at all times.

Rake Tasks

There are two rake tasks that build.sh calls: build and publish. The build task looks like this:

jekyll-repo/Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
desc "Build site"
task :build do
  Rake::Task["convertkit"].invoke
  Rake::Task["podcast"].invoke
  Rake::Task["microblog"].invoke
  Rake::Task["webmentions"].invoke
  sh "JEKYLL_ENV=production bundle exec jekyll b"
  sh "git add --all .;git commit -m 'cron build';git push;"
  sh "rm -rf /path/to/_site/"
  sh "cp -pr /path/to/repo/_site/ /path/to/web/_site/"
  sh "curl -X POST https://micro.blog/ping?url=https://joebuhlig.com/microblog/feed.xml"
  Rake::Task["microblog_webmentions"].invoke
end

I won’t get into the other rake tasks here. That’s for another day. For this, the important pieces are the sh lines. All they do is build the site, commit the changes, delete the old _site directory, copy the newly generated _site directory to the published web directory, and then ping the Micro.Blog service to update my Micro.Blog feed. I do this last step to make sure the post is picked up right away. Basically, I became tired of waiting for it to propagate on its own.

The publish task has a different intent. It runs when there is no new commit found. Here’s what it looks like:

jekyll-repo/Rakefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
desc "Publish scheduled posts"
task :publish do
  update = false
  today = Time.now
  Dir['_posts/*','_microblogs/*'].each do |filename|
    file = File.open("#{filename}").each_line do |line|
      if line.start_with?("date: ")
        post_date = Time.parse(line.split("date:")[1])
        time_between = today - post_date
        if time_between < 300 and time_between > 0
          puts filename
          update = true
        end
      end
    end
    file.close
  end
  last_updated_file = File.open("_data/webmentions/last-id.txt")
  last_id = last_updated_file.read.strip
  payload = open("https://webmention.io/api/mentions.json?token=MYTOKEN&since_id=#{last_id}")
  if JSON.parse(payload.read)["links"].count > 0
    update = true
  end

  last_updated_file = File.open("_data/microblog/last-id.txt")
  last_id = last_updated_file.read.strip
  payload = open('http://micro.blog/feeds/joebuhlig.json')
  JSON.parse(payload.read)["items"].each do |item|
    url = URI.parse(item["url"])
    if url.host == "joebuhlig.com"
      if item['id'] > last_id
        update = true
        break
      end
    end
  end

 if update
    Rake::Task["build"].invoke
  end
end

There’s a lot more going on here, obviously. But here’s the gist of it. It searches the _posts and _microblogs directories for files that are dated within the last five minutes. If you recall, the cron job runs every five minutes. So it only needs to determine if there is a post with a date in the last five minutes. If no, the job is done and can wait for the next run five minutes later. If yes, it tells the build task to run.

You’ll also note a webmention section here. This script also checks to see if there are any new webmentions collected for my posts and microblogs. Again, if no, be done. If yes, run the build task.

Exclusions

In Jekyll, any file that starts with a period or an underscore is kept out of the _site directory by default. But there are others that I find need removed as well. This is pretty easy. I have the following added to the exclude item of my _config.yml file.

jekyll-repo/_config.yml
1
2
3
4
5
6
7
8
9
10
11
12
exclude:
  - Rakefile
  - Gemfile
  - Gemfile.lock
  - node_modules
  - vendor/bundle
  - vendor/cache
  - vendor/gems
  - vendor/ruby
  - config
  - Capfile
  - build.sh

Putting It All Together

In practice, all of this works allows very simple actions. To make an edit to my site, I merely need to commit the change. No need to build the site and copy it to the correct directory on the web server.

This also means that to publish a new post or microblog in the future, I simply need to add a future date to the front matter. Within five minutes of the date passing, the article or microblog will post on its own. And that’s refreshing.

« The Best iOS Apps With TextExpander Integration profile-pic-square-small.jpgJoe Buhlig

an analog mind in a digital world

microblog.svg?v=39 mastodon.svg?v=39 twitter.svg?v=39 reddit.svg?v=39 instagram.svg?v=39 github.svg?v=39 pinboard.svg?v=39 keybase.png?v=39 discourse.svg?v=39

Want to see my August 2020 Bullet Journal setup?

Join 1,514 subscribers!

I'll send you the link to a six-minute overview video of my August 2020 spreads when you sign up for my newsletter, The Weekly Impulse.

Site Analytics

I use Fathom Analytics on this site because I care about your privacy. And if you ever want to see the stats collected and the data I see, check out the live analytics here.

Amazon Affiliate

joebuhlig.com is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means to earn fees when linking to Amazon.com and affiliated sites.

Disclaimer

Disclosure of Material Connection: Some of the links in the post above might be “affiliate links.” This means if you click on the link and purchase the item, I will receive an affiliate commission. Regardless, I only recommend products or services I use personally and believe will add value to my readers. I am disclosing this in accordance with the Federal Trade Commission’s 16 CFR, Part 255: “Guides Concerning the Use of Endorsements and Testimonials in Advertising.”

an analog mind in a digital world

👋 I'm Joe Buhlig. I strive to build productivity systems that stand the test of time and help me do more than check boxes. I'm here to help you do the same.

🎙 I read a lot of books and talk about it.

🐿 I can't focus on one thing for long, so I write a lot of code for an eclectic grouping of projects.

📓 And I'm a bit obsessed with finding non-proprietary solutions to digital problems. Thus, text files for the win! 🎉

MN U.S.A 1986-09-30
  • all
  • articles
  • code
  • likes
  • notes
  • photos
  • replies
  • reposts
  • steps
  • videos
coaching newsletter contact
© 2014-2025 by Joe Buhlig