diff --git a/db_schema.sql b/db_schema.sql
index ef074b6e21b1eb1f05f1f0b1dfbcc1a91faa3a55..d02c4fabd6aa4ef0f6e2df62d01a75a67463eb4c 100644
--- a/db_schema.sql
+++ b/db_schema.sql
@@ -125,14 +125,11 @@ CREATE TABLE IF NOT EXISTS `site_texts` (
   `modified_by` text NOT NULL
 );
 CREATE TABLE IF NOT EXISTS `log` (
-	`ip` varchar(64),
-	`id` varchar(64),
+	`id` INTEGER,
 	`time` datetime NOT NULL,
 	`date` datetime NOT NULL,
-	`source` varchar(8),
-	`object` varchar(10),
-	`obj_id` INTEGER,
-	`path` varchar(255) NOT NULL
+	`source` INTEGER,
+	`video` INTEGER
 );
 CREATE TABLE IF NOT EXISTS `logcache` (
 	`req` varchar(64),
diff --git a/server.py b/server.py
index a664a9b465d072be08f7b81882f2d80e1d52fab4..4ae2bed0c5388b0bb17b0d8fc47e29a04543a8dd 100644
--- a/server.py
+++ b/server.py
@@ -527,11 +527,10 @@ def auth(): # For use with nginx auth_request
 		return 'Internal Server Error', 500
 	url = request.headers['X-Original-Uri'].lstrip(config['VIDEOPREFIX'])
 	ip = request.headers.get('X-Real-IP', '')
-	if 'tracking' in request.cookies:
-		cookie = request.cookies['tracking']
+	if request.cookies.get('tracking', '') and request.cookies['tracking'].isdigit():
+		cookie = int(request.cookies['tracking'])
 	else:
-		cookie = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))
-	#	r.set_cookie('tracking', request.cookies.get('tracking', ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))), max_age=2147483647)
+		cookie = random.getrandbits(8*8-1)
 	if url.endswith('jpg') or ismod():
 		return "OK", 200
 	perms = query('''SELECT videos.path, videos.id AS vid, perm.*
@@ -552,11 +551,11 @@ def auth(): # For use with nginx auth_request
 		password = auth.password
 	if checkperm(perms, username=username, password=password):
 		try:
-			modify('INSERT INTO log (ip, id, `time`, `date`, object, obj_id, path) VALUES (?, ?, ?, "video", ?, ?)', ip, cookie, datetime.now(), datetime.combine(date.today(), time()), perms[0]['vid'], url)
+			modify('INSERT INTO log (id, `time`, `date`, video, source) VALUES (?, ?, ?, ?, 1)', cookie, datetime.now(), datetime.combine(date.today(), time()), perms[0]['vid'])
 		except:
 			pass
 		r = make_response('OK', 200)
-		r.set_cookie('tracking', cookie, max_age=2147483647) # Many many years
+		r.set_cookie('tracking', str(cookie), max_age=2147483647) # Many many years
 		return r
 	password_auth = False
 	for perm in perms:
diff --git a/stats.py b/stats.py
index 0265bf10cbe4f70b0e53b4de240ffa88f0950d48..f4d03463903601e3944c6ce653e702e6cd624ba2 100644
--- a/stats.py
+++ b/stats.py
@@ -10,13 +10,13 @@ def stats():
 	return render_template('stats.html')
 
 statsqueries = {}
-statsqueries['formats_views'] = "SELECT formats.description AS x, count(DISTINCT log.id) AS y FROM log JOIN videos ON (videos.id = log.obj_id) JOIN formats ON (formats.id = videos.video_format) GROUP BY formats.id"
+statsqueries['formats_views'] = "SELECT formats.description AS x, count(DISTINCT log.id) AS y FROM log JOIN videos ON (videos.id = log.video) JOIN formats ON (formats.id = videos.video_format) GROUP BY formats.id"
 statsqueries['course_count'] = "SELECT semester AS x, count(id) AS y FROM courses GROUP BY semester"
 statsqueries['lectures_count'] = "SELECT semester AS x, count(lectures.id) AS y FROM lectures JOIN courses ON (courses.id = lectures.course_id) GROUP BY semester"
 statsqueries['categories_courses'] = "SELECT courses.subject AS x, count(courses.id) AS y FROM courses GROUP BY courses.subject ORDER BY y DESC LIMIT 100"
 statsqueries['organizer_courses'] = "SELECT courses.organizer AS x, count(courses.id) AS y FROM courses GROUP BY courses.organizer ORDER BY y DESC LIMIT 100"
 statsqueries['categories_lectures'] = "SELECT courses.subject AS x, count(lectures.id) AS y FROM lectures JOIN courses ON (courses.id = lectures.course_id) WHERE lectures.visible GROUP BY courses.subject ORDER BY y DESC LIMIT 100"
-statsqueries['lecture_views'] = "SELECT lectures.time AS x, count(DISTINCT log.id) AS y FROM log JOIN videos ON (videos.id = log.obj_id) JOIN lectures ON (lectures.id = videos.lecture_id) WHERE (lectures.course_id = ?) GROUP BY lectures.id ORDER BY lectures.time"
+statsqueries['lecture_views'] = "SELECT lectures.time AS x, count(DISTINCT log.id) AS y FROM log JOIN videos ON (videos.id = log.video) JOIN lectures ON (lectures.id = videos.lecture_id) WHERE (lectures.course_id = ?) GROUP BY lectures.id ORDER BY lectures.time"
 
 def plotly_date_handler(obj):
 	return obj.strftime("%Y-%m-%d %H:%M:%S")
@@ -39,15 +39,16 @@ def stats_generic(req, param=None):
 
 @app.route('/stats/viewsperday/<req>')
 @app.route('/stats/viewsperday/<req>/<param>')
+@mod_required
 def stats_viewsperday(req, param=""):
 	update_expr = 'INSERT INTO logcache (req, param, trace, date, value) (SELECT "%s", ?, trace, date, y FROM (%s) AS cachetmp WHERE date < ?)'
 	query_expr = '(SELECT date, trace, value AS y FROM logcache WHERE req = "%s" AND param = ?) UNION (SELECT * FROM (%s) AS cachetmp)'
 	date_subexpr = '(SELECT CASE WHEN MAX(date) IS NULL THEN "2000-00-00" ELSE MAX(date) END FROM `logcache` WHERE req = "%s" AND param = ?)'
 	queries = {
-		'lecture': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id JOIN formats ON formats.id = videos.video_format WHERE log.date > %T AND videos.lecture_id = ? GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id WHERE log.date > %T AND videos.lecture_id = ? GROUP BY log.date)',
-		'course': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id JOIN lectures ON lectures.id = videos.lecture_id JOIN formats ON formats.id = videos.video_format WHERE log.date > %T AND lectures.course_id = ? GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id JOIN lectures ON lectures.id = videos.lecture_id WHERE log.date > %T AND lectures.course_id = ? GROUP BY log.date)',
-		'global': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id JOIN formats ON formats.id = videos.video_format WHERE log.date > %T GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log WHERE log.date > %T GROUP BY log.date)',
-		'courses': 'SELECT log.date AS date, courses.handle AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.obj_id JOIN lectures ON lectures.id = videos.lecture_id JOIN courses ON courses.id = lectures.course_id WHERE log.date > %T GROUP BY log.date, courses.id'
+		'lecture': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video JOIN formats ON formats.id = videos.video_format WHERE log.date > %T AND videos.lecture_id = ? GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video WHERE log.date > %T AND videos.lecture_id = ? GROUP BY log.date)',
+		'course': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video JOIN lectures ON lectures.id = videos.lecture_id JOIN formats ON formats.id = videos.video_format WHERE log.date > %T AND lectures.course_id = ? GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video JOIN lectures ON lectures.id = videos.lecture_id WHERE log.date > %T AND lectures.course_id = ? GROUP BY log.date)',
+		'global': '(SELECT log.date AS date, formats.description AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video JOIN formats ON formats.id = videos.video_format WHERE log.date > %T GROUP BY log.date, videos.video_format) UNION (SELECT log.date AS date, "total" AS trace, COUNT(DISTINCT log.id) AS y FROM log WHERE log.date > %T GROUP BY log.date)',
+		'courses': 'SELECT log.date AS date, courses.handle AS trace, COUNT(DISTINCT log.id) AS y FROM log JOIN videos ON videos.id = log.video JOIN lectures ON lectures.id = videos.lecture_id JOIN courses ON courses.id = lectures.course_id WHERE log.date > %T GROUP BY log.date, courses.id'
 	}
 	expr = queries[req]
 	expr = expr.replace('%T', date_subexpr%('viewsperday.'+req))