diff --git a/services/wordpress/wordpress-downloads.service.js b/services/wordpress/wordpress-downloads.service.js
index 8728caa45f1fdef0f4cd32df5b378e5aa42904bc..f931cf41b09f2e7059663243dd8c99cef21a2e98 100644
--- a/services/wordpress/wordpress-downloads.service.js
+++ b/services/wordpress/wordpress-downloads.service.js
@@ -4,7 +4,7 @@ const Joi = require('@hapi/joi')
 const { metric } = require('../text-formatters')
 const { downloadCount } = require('../color-formatters')
 const BaseWordpress = require('./wordpress-base')
-const { BaseJsonService, NotFound } = require('..')
+const { NotFound } = require('..')
 
 const dateSchema = Joi.object()
   .pattern(Joi.date().iso(), Joi.number().integer())
@@ -21,6 +21,29 @@ const extensionData = {
   },
 }
 
+const intervalMap = {
+  dd: {
+    limit: 1,
+    messageSuffix: '/day',
+  },
+  dw: {
+    limit: 7,
+    messageSuffix: '/week',
+  },
+  dm: {
+    limit: 30,
+    messageSuffix: '/month',
+  },
+  dy: {
+    limit: 365,
+    messageSuffix: '/year',
+  },
+  dt: {
+    limit: null,
+    messageSuffix: '',
+  },
+}
+
 function DownloadsForExtensionType(extensionType) {
   const { capt, exampleSlug } = extensionData[extensionType]
 
@@ -35,8 +58,8 @@ function DownloadsForExtensionType(extensionType) {
 
     static get route() {
       return {
-        base: `wordpress/${extensionType}/dt`,
-        pattern: ':slug',
+        base: `wordpress/${extensionType}`,
+        pattern: ':interval(dd|dw|dm|dy|dt)/:slug',
       }
     }
 
@@ -44,8 +67,8 @@ function DownloadsForExtensionType(extensionType) {
       return [
         {
           title: `WordPress ${capt} Downloads`,
-          namedParams: { slug: exampleSlug },
-          staticPreview: this.render({ downloads: 200000 }),
+          namedParams: { interval: 'dm', slug: exampleSlug },
+          staticPreview: this.render({ interval: 'dm', downloads: 200000 }),
         },
       ]
     }
@@ -54,19 +77,50 @@ function DownloadsForExtensionType(extensionType) {
       return { label: 'downloads' }
     }
 
-    static render({ downloads }) {
+    static render({ interval, downloads }) {
+      const { messageSuffix } = intervalMap[interval]
+
       return {
-        message: metric(downloads),
+        message: `${metric(downloads)}${messageSuffix}`,
         color: downloadCount(downloads),
       }
     }
 
-    async handle({ slug }) {
-      const { downloaded: downloads } = await this.fetch({
-        extensionType,
-        slug,
-      })
-      return this.constructor.render({ downloads })
+    async handle({ interval, slug }) {
+      const { limit } = intervalMap[interval]
+      let downloads
+      if (limit === null) {
+        const { downloaded: _downloads } = await this.fetch({
+          extensionType,
+          slug,
+        })
+        downloads = _downloads
+      } else {
+        const ext_type = extensionType === 'plugin' ? 'plugin' : 'themes'
+        const json = await this._requestJson({
+          schema: dateSchema,
+          url: `https://api.wordpress.org/stats/${ext_type}/1.0/downloads.php`,
+          options: {
+            qs: {
+              slug,
+              limit,
+            },
+          },
+        })
+        const size = Object.keys(json).length
+        downloads = Object.values(json).reduce(
+          (a, b) => parseInt(a) + parseInt(b)
+        )
+        // This check is for non-existent and brand-new plugins both having new stats.
+        // Non-Existent plugins results are the same as a brandspanking new plugin with no downloads.
+        if (downloads <= 0 && size <= 1) {
+          throw new NotFound({
+            prettyMessage: `${extensionType} not found or too new`,
+          })
+        }
+      }
+
+      return this.constructor.render({ interval, downloads })
     }
   }
 }
@@ -121,100 +175,7 @@ function InstallsForExtensionType(extensionType) {
   }
 }
 
-function DownloadsForInterval(interval) {
-  const { base, messageSuffix = '', query, name } = {
-    day: {
-      base: 'wordpress/plugin/dd',
-      messageSuffix: '/day',
-      query: 1,
-      name: 'WordpressDownloadsDay',
-    },
-    week: {
-      base: 'wordpress/plugin/dw',
-      messageSuffix: '/week',
-      query: 7,
-      name: 'WordpressDownloadsWeek',
-    },
-    month: {
-      base: 'wordpress/plugin/dm',
-      messageSuffix: '/month',
-      query: 30,
-      name: 'WordpressDownloadsMonth',
-    },
-    year: {
-      base: 'wordpress/plugin/dy',
-      messageSuffix: '/year',
-      query: 365,
-      name: 'WordpressDownloadsYear',
-    },
-  }[interval]
-
-  return class WordpressDownloads extends BaseJsonService {
-    static get name() {
-      return name
-    }
-
-    static get category() {
-      return 'downloads'
-    }
-
-    static get route() {
-      return {
-        base,
-        pattern: ':slug',
-      }
-    }
-
-    static get examples() {
-      return [
-        {
-          title: 'WordPress Plugin Downloads',
-          namedParams: { slug: 'bbpress' },
-          staticPreview: this.render({ downloads: 30000 }),
-        },
-      ]
-    }
-
-    static get defaultBadgeData() {
-      return { label: 'downloads' }
-    }
-
-    static render({ downloads }) {
-      return {
-        message: `${metric(downloads)}${messageSuffix}`,
-        color: downloadCount(downloads),
-      }
-    }
-
-    async handle({ slug }) {
-      const json = await this._requestJson({
-        schema: dateSchema,
-        url: `https://api.wordpress.org/stats/plugin/1.0/downloads.php`,
-        options: {
-          qs: {
-            slug,
-            limit: query,
-          },
-        },
-      })
-      const size = Object.keys(json).length
-      const downloads = Object.values(json).reduce(
-        (a, b) => parseInt(a) + parseInt(b)
-      )
-      // This check is for non-existent and brand-new plugins both having new stats.
-      // Non-Existent plugins results are the same as a brandspanking new plugin with no downloads.
-      if (downloads <= 0 && size <= 1) {
-        throw new NotFound({ prettyMessage: 'plugin not found or too new' })
-      }
-      return this.constructor.render({ downloads })
-    }
-  }
-}
-
-const intervalServices = ['day', 'week', 'month', 'year'].map(
-  DownloadsForInterval
-)
 const downloadServices = ['plugin', 'theme'].map(DownloadsForExtensionType)
 const installServices = ['plugin', 'theme'].map(InstallsForExtensionType)
-const modules = [...intervalServices, ...downloadServices, ...installServices]
+const modules = [...downloadServices, ...installServices]
 module.exports = modules
diff --git a/services/wordpress/wordpress-downloads.tester.js b/services/wordpress/wordpress-downloads.tester.js
index 1bdc79b20bb2b0a4048b80f80469f2e1e6377283..a455dbc8aea751c6f31a3242688f1929eabd9192 100644
--- a/services/wordpress/wordpress-downloads.tester.js
+++ b/services/wordpress/wordpress-downloads.tester.js
@@ -15,6 +15,7 @@ t.create('Plugin Downloads - Total')
     label: 'downloads',
     message: isMetric,
   })
+
 t.create('Plugin Downloads - Active')
   .get('/plugin/installs/akismet.json')
   .expectBadge({
@@ -43,12 +44,20 @@ t.create('Plugin Downloads - Month')
     message: isMetricOverTimePeriod,
   })
 
+t.create('Plugin Downloads - Year')
+  .get('/plugin/dy/akismet.json')
+  .expectBadge({
+    label: 'downloads',
+    message: isMetricOverTimePeriod,
+  })
+
 t.create('Theme Downloads - Total')
   .get('/theme/dt/twentyseventeen.json')
   .expectBadge({
     label: 'downloads',
     message: isMetric,
   })
+
 t.create('Theme Downloads - Active')
   .get('/theme/installs/twentyseventeen.json')
   .expectBadge({
@@ -56,12 +65,41 @@ t.create('Theme Downloads - Active')
     message: isMetric,
   })
 
+t.create('Theme Downloads - Day')
+  .get('/theme/dd/twentyseventeen.json')
+  .expectBadge({
+    label: 'downloads',
+    message: isMetricOverTimePeriod,
+  })
+
+t.create('Theme Downloads - Week')
+  .get('/theme/dw/twentyseventeen.json')
+  .expectBadge({
+    label: 'downloads',
+    message: isMetricOverTimePeriod,
+  })
+
+t.create('Theme Downloads - Month')
+  .get('/theme/dm/twentyseventeen.json')
+  .expectBadge({
+    label: 'downloads',
+    message: isMetricOverTimePeriod,
+  })
+
+t.create('Theme Downloads - Year')
+  .get('/theme/dy/twentyseventeen.json')
+  .expectBadge({
+    label: 'downloads',
+    message: isMetricOverTimePeriod,
+  })
+
 t.create('Plugin Downloads - Total | Not Found')
   .get('/plugin/dt/100.json')
   .expectBadge({
     label: 'downloads',
     message: 'not found',
   })
+
 t.create('Plugin Downloads - Active | Not Found')
   .get('/plugin/installs/100.json')
   .expectBadge({
@@ -90,15 +128,51 @@ t.create('Plugin Downloads - Month | Not Found')
     message: 'plugin not found or too new',
   })
 
+t.create('Plugin Downloads - Year | Not Found')
+  .get('/plugin/dy/100.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'plugin not found or too new',
+  })
+
 t.create('Theme Downloads - Total | Not Found')
   .get('/theme/dt/100.json')
   .expectBadge({
     label: 'downloads',
     message: 'not found',
   })
+
 t.create('Theme Downloads - Active | Not Found')
   .get('/theme/installs/100.json')
   .expectBadge({
     label: 'active installs',
     message: 'not found',
   })
+
+t.create('Theme Downloads - Day | Not Found')
+  .get('/theme/dd/100.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'theme not found or too new',
+  })
+
+t.create('Theme Downloads - Week | Not Found')
+  .get('/theme/dw/100.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'theme not found or too new',
+  })
+
+t.create('Theme Downloads - Month | Not Found')
+  .get('/theme/dm/100.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'theme not found or too new',
+  })
+
+t.create('Theme Downloads - Year | Not Found')
+  .get('/theme/dy/100.json')
+  .expectBadge({
+    label: 'downloads',
+    message: 'theme not found or too new',
+  })