diff --git a/frontend/src/components/PointInfo.vue b/frontend/src/components/PointInfo.vue
index 7dc5ca2..87f64fa 100644
--- a/frontend/src/components/PointInfo.vue
+++ b/frontend/src/components/PointInfo.vue
@@ -55,7 +55,7 @@
           {{ device.name }}
         </p>
 
-        <p class="battery" :style="{ color: batteryColor }" v-if="point.battery">
+        <p class="battery" :style="{ color: batteryColor ?? 'initial' }" v-if="point.battery">
           <font-awesome-icon :icon="batteryIconClass" />
           <span>{{ point.battery }}%</span>
         </p>
diff --git a/frontend/src/components/Timeline.vue b/frontend/src/components/Timeline.vue
index 7cbb9fe..49cfecc 100644
--- a/frontend/src/components/Timeline.vue
+++ b/frontend/src/components/Timeline.vue
@@ -21,6 +21,13 @@
                 :title="(showMetrics.speed ? 'Hide' : 'Show') + ' speed'">
           <font-awesome-icon icon="tachometer-alt" />
         </button>
+
+        <button @click="toggleMetric('battery')"
+                :class="{ selected: showMetrics.battery }"
+                :title="(showMetrics.battery ? 'Hide' : 'Show') + ' battery level'"
+                v-if="hasBatteryInfo">
+          <font-awesome-icon icon="battery-full" />
+        </button>
       </div>
 
       <div class="page-button-container">
@@ -128,12 +135,25 @@ export default {
       })
     },
 
+    hasBatteryInfo(): boolean {
+      return this.points.some((point: GPSPoint) => point.battery != null)
+    },
+
+    battery(): (number | null)[] {
+      return this.points
+        .map((point: GPSPoint) => point.battery ?? null)
+    },
+
     speed(): number[] {
       if (!this.points.length) {
         return []
       }
 
       return this.points.map((point: GPSPoint, index: number) => {
+        if (point.speed != null) {
+          return point.speed
+        }
+
         if (index === 0) {
           return 0
         }
@@ -185,6 +205,19 @@ export default {
         )
       }
 
+      if (this.showMetrics.battery) {
+        datasets.push(
+          {
+            label: 'Battery (%)',
+            backgroundColor: '#0989f8',
+            borderColor: '#5959a8',
+            fill: false,
+            data: this.battery,
+            yAxisID: 'percentage',
+          }
+        )
+      }
+
       return {
         labels: this.points.map((point: GPSPoint) => point.timestamp),
         datasets: datasets,
@@ -242,6 +275,31 @@ export default {
         }
       }
 
+      if (this.showMetrics.battery) {
+        let position = 'left'
+        if (yAxes.meters || yAxes.speed) {
+          position = 'right'
+        }
+
+        yAxes.percentage = {
+          type: 'linear',
+          position: position,
+          display: true,
+          min: 0,
+          max: 100,
+          ticks: {
+            beginAtZero: true,
+          },
+          title: {
+            display: true,
+            text: 'Percentage',
+          },
+          grid: {
+            drawOnChartArea: false,
+          },
+        }
+      }
+
       const xTicks = {} as { min?: Date, max?: Date }
       if (this.points.length > 1) {
         xTicks.min = this.points[0].timestamp
diff --git a/frontend/src/models/TimelineMetricsConfiguration.ts b/frontend/src/models/TimelineMetricsConfiguration.ts
index 5794771..ef6d0ba 100644
--- a/frontend/src/models/TimelineMetricsConfiguration.ts
+++ b/frontend/src/models/TimelineMetricsConfiguration.ts
@@ -2,13 +2,14 @@ class TimelineMetricsConfiguration {
   public altitude: boolean = false;
   public distance: boolean = true;
   public speed: boolean = false;
+  public battery: boolean = false;
 
   constructor(data: any | null = null) {
     if (!data) {
       return;
     }
 
-    for (const key of ['altitude', 'distance', 'speed']) {
+    for (const key of ['altitude', 'distance', 'speed', 'battery']) {
       const value = String(
         data[key] ?? data['show' + key.charAt(0).toUpperCase() + key.slice(1)]
       )
@@ -39,13 +40,16 @@ class TimelineMetricsConfiguration {
       case 'speed':
         this.speed = !this.speed;
         break;
+      case 'battery':
+        this.battery = !this.battery;
+        break;
       default:
         throw new TypeError(`Invalid timeline metric: ${metric}`);
     }
   }
 
   toQuery(): Record<string, string> {
-    return ['altitude', 'distance', 'speed'].reduce((acc: Record<string, string>, key: string) => {
+    return ['altitude', 'distance', 'speed', 'battery'].reduce((acc: Record<string, string>, key: string) => {
       acc['show' + key.charAt(0).toUpperCase() + key.slice(1)] = String((this as any)[key]);
       return acc;
     }, {});