diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php
index 6b2d6928d..3cb8237ea 100644
--- a/app/Http/Controllers/BookController.php
+++ b/app/Http/Controllers/BookController.php
@@ -42,8 +42,9 @@ class BookController extends Controller
     public function index()
     {
         $books = $this->bookRepo->getAllPaginated(10);
-        $recents = $this->signedIn ? $this->bookRepo->getRecentlyViewed(10, 0) : false;
-        return view('books/index', ['books' => $books, 'recents' => $recents]);
+        $recents = $this->signedIn ? $this->bookRepo->getRecentlyViewed(4, 0) : false;
+        $popular = $this->bookRepo->getPopular(4, 0);
+        return view('books/index', ['books' => $books, 'recents' => $recents, 'popular' => $popular]);
     }
 
     /**
diff --git a/app/Repos/BookRepo.php b/app/Repos/BookRepo.php
index 9be77defe..110426bbd 100644
--- a/app/Repos/BookRepo.php
+++ b/app/Repos/BookRepo.php
@@ -77,6 +77,11 @@ class BookRepo
         return Views::getUserRecentlyViewed($count, $page, $this->book);
     }
 
+    public function getPopular($count = 10, $page = 0)
+    {
+        return Views::getPopular($count, $page, $this->book);
+    }
+
     /**
      * Get a book by slug
      * @param $slug
diff --git a/app/Services/ViewService.php b/app/Services/ViewService.php
index 475500927..5b800d939 100644
--- a/app/Services/ViewService.php
+++ b/app/Services/ViewService.php
@@ -44,6 +44,29 @@ class ViewService
         return 1;
     }
 
+
+    /**
+     * Get the entities with the most views.
+     * @param int        $count
+     * @param int        $page
+     * @param bool|false $filterModel
+     */
+    public function getPopular($count = 10, $page = 0, $filterModel = false)
+    {
+        $skipCount = $count * $page;
+        $query = $this->view->select('id', 'viewable_id', 'viewable_type', \DB::raw('SUM(views) as view_count'))
+            ->groupBy('viewable_id', 'viewable_type')
+            ->orderBy('view_count', 'desc');
+
+        if($filterModel) $query->where('viewable_type', '=', get_class($filterModel));
+
+        $views = $query->with('viewable')->skip($skipCount)->take($count)->get();
+        $viewedEntities = $views->map(function ($item) {
+            return $item->viewable()->getResults();
+        });
+        return $viewedEntities;
+    }
+
     /**
      * Get all recently viewed entities for the current user.
      * @param int         $count
diff --git a/resources/views/books/index.blade.php b/resources/views/books/index.blade.php
index 32742d126..f28b7c1dd 100644
--- a/resources/views/books/index.blade.php
+++ b/resources/views/books/index.blade.php
@@ -34,11 +34,22 @@
                 @endif
             </div>
             <div class="col-sm-4 col-sm-offset-1">
+                <div id="recents">
+                    @if($recents)
+                        <div class="margin-top large">&nbsp;</div>
+                        <h3>Recently Viewed</h3>
+                        @include('partials/entity-list', ['entities' => $recents])
+                    @endif
+                </div>
                 <div class="margin-top large">&nbsp;</div>
-                @if($recents)
-                    <h3>Recently Viewed</h3>
-                    @include('partials/entity-list', ['entities' => $recents])
-                @endif
+                <div id="popular">
+                    <h3>Popular Books</h3>
+                    @if(count($popular) > 0)
+                        @include('partials/entity-list', ['entities' => $popular])
+                    @else
+                        <p class="text-muted">The most popular books will appear here.</p>
+                    @endif
+                </div>
             </div>
         </div>
     </div>
diff --git a/resources/views/partials/entity-list.blade.php b/resources/views/partials/entity-list.blade.php
index 058b0b24f..a357a70fa 100644
--- a/resources/views/partials/entity-list.blade.php
+++ b/resources/views/partials/entity-list.blade.php
@@ -1,6 +1,6 @@
 
 @if(count($entities) > 0)
-    @foreach($entities as $entity)
+    @foreach($entities as $index => $entity)
         @if($entity->isA('page'))
             @include('pages/list-item', ['page' => $entity])
         @elseif($entity->isA('book'))
@@ -8,7 +8,11 @@
         @elseif($entity->isA('chapter'))
             @include('chapters/list-item', ['chapter' => $entity, 'hidePages' => true])
         @endif
-        <hr>
+
+        @if($index !== count($entities) - 1)
+            <hr>
+        @endif
+
     @endforeach
 @else
     <p class="text-muted">
diff --git a/tests/ActivityTrackingTest.php b/tests/ActivityTrackingTest.php
new file mode 100644
index 000000000..8a237f880
--- /dev/null
+++ b/tests/ActivityTrackingTest.php
@@ -0,0 +1,38 @@
+<?php
+
+use Illuminate\Foundation\Testing\WithoutMiddleware;
+use Illuminate\Foundation\Testing\DatabaseMigrations;
+use Illuminate\Foundation\Testing\DatabaseTransactions;
+
+class ActivityTrackingTest extends TestCase
+{
+
+    public function testRecentlyViewedBooks()
+    {
+        $books = \BookStack\Book::all()->take(10);
+
+        $this->asAdmin()->visit('/books')
+            ->dontSeeInElement('#recents', $books[0]->name)
+            ->dontSeeInElement('#recents', $books[1]->name)
+            ->visit($books[0]->getUrl())
+            ->visit($books[1]->getUrl())
+            ->visit('/books')
+            ->seeInElement('#recents', $books[0]->name)
+            ->seeInElement('#recents', $books[1]->name);
+    }
+
+    public function testPopularBooks()
+    {
+        $books = \BookStack\Book::all()->take(10);
+
+        $this->asAdmin()->visit('/books')
+            ->dontSeeInElement('#popular', $books[0]->name)
+            ->dontSeeInElement('#popular', $books[1]->name)
+            ->visit($books[0]->getUrl())
+            ->visit($books[1]->getUrl())
+            ->visit($books[0]->getUrl())
+            ->visit('/books')
+            ->seeInNthElement('#popular .book', 0, $books[0]->name)
+            ->seeInNthElement('#popular .book', 1, $books[1]->name);
+    }
+}
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 3f7d846f7..3a0967c8e 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -48,4 +48,31 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
             $settings->put($key, $value);
         }
     }
+
+    /**
+     * Assert that a given string is seen inside an element.
+     *
+     * @param  bool|string|null $element
+     * @param  integer          $position
+     * @param  string           $text
+     * @param  bool             $negate
+     * @return $this
+     */
+    protected function seeInNthElement($element, $position, $text, $negate = false)
+    {
+        $method = $negate ? 'assertNotRegExp' : 'assertRegExp';
+
+        $rawPattern = preg_quote($text, '/');
+
+        $escapedPattern = preg_quote(e($text), '/');
+
+        $content = $this->crawler->filter($element)->eq($position)->html();
+
+        $pattern = $rawPattern == $escapedPattern
+            ? $rawPattern : "({$rawPattern}|{$escapedPattern})";
+
+        $this->$method("/$pattern/i", $content);
+
+        return $this;
+    }
 }