diff --git a/reader/templates/reader/book_read/bookreader_save.js b/reader/templates/reader/book_read/bookreader_save.js
new file mode 100644
index 0000000000000000000000000000000000000000..0a8ca998ad228b180923d9c3ec3c42635d03da6a
--- /dev/null
+++ b/reader/templates/reader/book_read/bookreader_save.js
@@ -0,0 +1,41 @@
+let last_save_time = new Date();
+let saveTimeout = null;
+
+function realSaveProgress(location, percentage) {
+    let data = {
+        csrfmiddlewaretoken: "{{ csrf_token }}",
+        last_progress_cfi: location,
+        last_progress_device: "Web Viewer",
+        percentage_read: percentage
+    };
+    console.log("Pushing saved progress: " + JSON.stringify(data));
+    $.ajax(
+        "{% url 'update_progress' book_id=book.id %}",
+        {
+            method: "POST",
+            data: data
+        }
+    );
+    $("#lastsaved").html("Progress saved.");
+}
+
+function saveProgress(location, percentage) {
+    let current_time = new Date();
+    if (current_time - last_save_time > 5000) {
+        if (saveTimeout !== null) {
+            clearTimeout(saveTimeout);
+        }
+        saveTimeout = null;
+        realSaveProgress(location, percentage);
+        last_save_time = current_time;
+    } else {
+        // Don't save 'cause we don't want to lag out the server if the user is scrolling
+        $("#lastsaved").html("Unsaved progress - <a href=\"#\" onclick=\"realSaveProgress('" + location + "', " + percentage + "); return false;\">Click here to save now</a>");
+        // Set a timeout to autosave in 5 seconds in case we've stopped scrolling
+        if(saveTimeout === null) {
+            saveTimeout = setTimeout(function() {
+                saveProgress(location, percentage);
+            }, 5500);
+        }
+    }
+}
\ No newline at end of file
diff --git a/reader/templates/reader/book_read/epub_viewer.html b/reader/templates/reader/book_read/epub_viewer.html
index 34fc51aad8877f8cf8a4611ec6a41bf96a93e097..ea0df6a8fb7391882c603568bd99dca21134e923 100644
--- a/reader/templates/reader/book_read/epub_viewer.html
+++ b/reader/templates/reader/book_read/epub_viewer.html
@@ -18,7 +18,9 @@
                     <td class="ta-left">
                         <span class="ta-text">Now reading: {{ book.title }}</span>
                     </td>
-                    <td></td>
+                    <td>
+                        <span id="lastsaved">Not saved yet.</span>
+                    </td>
                     <td class="ta-right">
                         <span class="ta-text"><a href="{% url 'view_book' book.id %}" class="btn btn-primary">Back to book</a></span>
                     </td>
@@ -41,11 +43,17 @@
             height: "100%",
             snap: true
         });
-        let displayed = rendition.display();
+        {% if cfi_ref %}
+            let displayed = rendition.display("{{ cfi_ref }}");
+        {% else %}
+            let displayed = rendition.display();
+        {% endif %}
+
+        {% include "reader/book_read/bookreader_save.js" %}
 
         rendition.on("relocated", function(location){
             console.log(location);
-            // TODO Save location here
+            saveProgress(location.start.cfi, rendition.location.start.percentage / 100);
         });
 
         displayed.then(function(renderer){