jekyll-stats

A Jekyll plugin that adds a jekyll stats command to display site statistics.

Installation

Add to your Jekyll site's Gemfile:

gem "jekyll-stats"

Then run bundle install.

Usage

Run from your Jekyll site directory:

# Print stats to terminal
jekyll stats

# Save stats to _data/stats.json
jekyll stats --save

# Output raw JSON to stdout
jekyll stats --json

# Include drafts in calculations
jekyll stats --drafts

Terminal Output

Site Statistics
-----------------------------------
Posts: 127 (43,521 words, ~3h 38m read time)
Avg: 343 words | Longest: "My Best Post" (2,847 words)
First: 2019-03-14 | Last: 2025-12-18 (6.8 years)
Frequency: 1.6 posts/month

Posts by Year:
  2025: 

JSON Output

The --save flag writes _data/stats.json with this structure:

{
  "generated_at": "2025-12-21T09:30:00Z",
  "total_posts": 127,
  "total_words": 43521,
  "reading_minutes": 218,
  "average_words": 343,
  "longest_post": { "title": "My Best Post", "url": "/2024/01/my-best-post", "words": 2847 },
  "shortest_post": { "title": "Quick Note", "url": "/2024/03/quick-note", "words": 89 },
  "first_post": { "title": "Hello World", "url": "/2019/03/hello-world", "date": "2019-03-14" },
  "last_post": { "title": "Recent Post", "url": "/2025/12/recent-post", "date": "2025-12-18" },
  "years_active": 6.8,
  "posts_per_month": 1.6,
  "posts_by_year": [{ "year": 2025, "count": 24 }, { "year": 2024, "count": 38 }],
  "posts_by_month": [{ "month": "2025-12", "count": 3 }],
  "posts_by_day_of_week": { "monday": 23, "tuesday": 18, "wednesday": 15, "thursday": 20, "friday": 22, "saturday": 14, "sunday": 15 },
  "tags": [{ "name": "ruby", "count": 34 }, { "name": "opensource", "count": 28 }],
  "categories": [{ "name": "code", "count": 45 }, { "name": "cars", "count": 32 }],
  "drafts_count": 3
}

Building a Stats Page

After running jekyll stats --save, create a stats page using Liquid:

---
layout: page
title: Site Statistics
---

<p>
  <strong>{{ site.data.stats.total_posts }}</strong> posts,
  <strong>{{ site.data.stats.total_words | divided_by: 1000 }}k</strong> words,
  <strong>{{ site.data.stats.reading_minutes | divided_by: 60 }}</strong> hours of reading.
</p>

<p>
  Writing since {{ site.data.stats.first_post.date }} ({{ site.data.stats.years_active }} years).
  Averaging {{ site.data.stats.posts_per_month }} posts per month.
</p>

<h2>Posts by Year</h2>
<ul>
{% for year in site.data.stats.posts_by_year %}
  <li>{{ year.year }}: {{ year.count }} posts</li>
{% endfor %}
</ul>

<h2>Top Tags</h2>
<ul>
{% for tag in site.data.stats.tags limit:10 %}
  <li>{{ tag.name }} ({{ tag.count }})</li>
{% endfor %}
</ul>

<h2>Extremes</h2>
<ul>
  <li>Longest: <a href="{{ site.data.stats.longest_post.url }}">{{ site.data.stats.longest_post.title }}</a> ({{ site.data.stats.longest_post.words }} words)</li>
  <li>Shortest: <a href="{{ site.data.stats.shortest_post.url }}">{{ site.data.stats.shortest_post.title }}</a> ({{ site.data.stats.shortest_post.words }} words)</li>
</ul>

<h2>Day of Week</h2>
<p>
  I write most on
  {% assign max_day = "" %}
  {% assign max_count = 0 %}
  {% for day in site.data.stats.posts_by_day_of_week %}
    {% if day[1] > max_count %}
      {% assign max_day = day[0] %}
      {% assign max_count = day[1] %}
    {% endif %}
  {% endfor %}
  {{ max_day | capitalize }}s ({{ max_count }} posts).
</p>

Development

bin/setup
rake test

License

MIT License. See LICENSE for details.