diff --git a/.eslintrc.yml b/.eslintrc.yml
index 509cabf1dcf907572be9b700f7e42665189bd4e3..d9f322d1c7b607b6774192c34b58a5221ed0f32b 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -12,15 +12,40 @@ parserOptions:
   sourceType: 'script'
 
 overrides:
-  files:
-    - gatsby-browser.js
-  parserOptions:
-    sourceType: 'module'
+  - files:
+      - gatsby-browser.js
+    parserOptions:
+      sourceType: 'module'
+  - files:
+      - 'core/base-service/**/*.js'
+      - 'services/**/*.js'
+    rules:
+      sort-class-members/sort-class-members:
+        [
+          'warn',
+          {
+            order:
+              [
+                'name',
+                'category',
+                'isDeprecated',
+                'route',
+                'examples',
+                'defaultBadgeData',
+                'render',
+                'constructor',
+                'fetch',
+                'transform',
+                'handle',
+              ],
+          },
+        ]
 
 plugins:
   - mocha
   - no-extension-in-require
-  - 'chai-friendly'
+  - chai-friendly
+  - sort-class-members
 
 rules:
   # Disable some rules from eslint:recommended.
diff --git a/core/base-service/base.js b/core/base-service/base.js
index f4c4f0f58f0576cdc936810206db1dd6f46feb89..07c9b219a12f758b49d2305bdb3f6732b0df97a2 100644
--- a/core/base-service/base.js
+++ b/core/base-service/base.js
@@ -70,26 +70,6 @@ const serviceDataSchema = Joi.object({
   .required()
 
 module.exports = class BaseService {
-  constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
-    this._requestFetcher = sendAndCacheRequest
-    this._handleInternalErrors = handleInternalErrors
-  }
-
-  static render(props) {
-    throw new Error(`render() function not implemented for ${this.name}`)
-  }
-
-  /**
-   * Asynchronous function to handle requests for this service. Take the route
-   * parameters (as defined in the `route` property), perform a request using
-   * `this._sendAndCacheRequest`, and return the badge data.
-   */
-  async handle(namedParams, queryParams) {
-    throw new Error(`Handler not implemented for ${this.constructor.name}`)
-  }
-
-  // Metadata
-
   /**
    * Name of the category to sort this badge into (eg. "build"). Used to sort
    * the badges on the main shields.io website.
@@ -98,6 +78,10 @@ module.exports = class BaseService {
     throw new Error(`Category not set for ${this.name}`)
   }
 
+  static get isDeprecated() {
+    return false
+  }
+
   /**
    * Returns an object:
    *  - base: (Optional) The base path of the routes for this service. This is
@@ -127,17 +111,14 @@ module.exports = class BaseService {
     throw new Error(`Route not defined for ${this.name}`)
   }
 
-  static get isDeprecated() {
-    return false
-  }
-
-  /**
-   * Default data for the badge. Can include label, logo, and color. These
-   * defaults are used if the value is neither included in the service data
-   * from the handler nor overridden by the user via query parameters.
-   */
-  static get defaultBadgeData() {
-    return {}
+  static get _cacheLength() {
+    const cacheLengths = {
+      build: 30,
+      license: 3600,
+      version: 300,
+      debug: 60,
+    }
+    return cacheLengths[this.category]
   }
 
   /**
@@ -172,6 +153,15 @@ module.exports = class BaseService {
     return []
   }
 
+  /**
+   * Default data for the badge. Can include label, logo, and color. These
+   * defaults are used if the value is neither included in the service data
+   * from the handler nor overridden by the user via query parameters.
+   */
+  static get defaultBadgeData() {
+    return {}
+  }
+
   static validateDefinition() {
     assertValidCategory(this.category, `Category for ${this.name}`)
 
@@ -219,14 +209,53 @@ module.exports = class BaseService {
     return result
   }
 
-  static get _cacheLength() {
-    const cacheLengths = {
-      build: 30,
-      license: 3600,
-      version: 300,
-      debug: 60,
-    }
-    return cacheLengths[this.category]
+  static render(props) {
+    throw new Error(`render() function not implemented for ${this.name}`)
+  }
+
+  constructor({ sendAndCacheRequest }, { handleInternalErrors }) {
+    this._requestFetcher = sendAndCacheRequest
+    this._handleInternalErrors = handleInternalErrors
+  }
+
+  async _request({ url, options = {}, errorMessages = {} }) {
+    const logTrace = (...args) => trace.logTrace('fetch', ...args)
+    logTrace(emojic.bowAndArrow, 'Request', url, '\n', options)
+    const { res, buffer } = await this._requestFetcher(url, options)
+    logTrace(emojic.dart, 'Response status code', res.statusCode)
+    return checkErrorResponse.asPromise(errorMessages)({ buffer, res })
+  }
+
+  static _validate(
+    data,
+    schema,
+    {
+      prettyErrorMessage = 'invalid response data',
+      includeKeys = false,
+      allowAndStripUnknownKeys = true,
+    } = {}
+  ) {
+    return validate(
+      {
+        ErrorClass: InvalidResponse,
+        prettyErrorMessage,
+        includeKeys,
+        traceErrorMessage: 'Response did not match schema',
+        traceSuccessMessage: 'Response after validation',
+        allowAndStripUnknownKeys,
+      },
+      data,
+      schema
+    )
+  }
+
+  /**
+   * Asynchronous function to handle requests for this service. Take the route
+   * parameters (as defined in the `route` property), perform a request using
+   * `this._sendAndCacheRequest`, and return the badge data.
+   */
+  async handle(namedParams, queryParams) {
+    throw new Error(`Handler not implemented for ${this.constructor.name}`)
   }
 
   _handleError(error) {
@@ -398,35 +427,4 @@ module.exports = class BaseService {
       })
     )
   }
-
-  static _validate(
-    data,
-    schema,
-    {
-      prettyErrorMessage = 'invalid response data',
-      includeKeys = false,
-      allowAndStripUnknownKeys = true,
-    } = {}
-  ) {
-    return validate(
-      {
-        ErrorClass: InvalidResponse,
-        prettyErrorMessage,
-        includeKeys,
-        traceErrorMessage: 'Response did not match schema',
-        traceSuccessMessage: 'Response after validation',
-        allowAndStripUnknownKeys,
-      },
-      data,
-      schema
-    )
-  }
-
-  async _request({ url, options = {}, errorMessages = {} }) {
-    const logTrace = (...args) => trace.logTrace('fetch', ...args)
-    logTrace(emojic.bowAndArrow, 'Request', url, '\n', options)
-    const { res, buffer } = await this._requestFetcher(url, options)
-    logTrace(emojic.dart, 'Response status code', res.statusCode)
-    return checkErrorResponse.asPromise(errorMessages)({ buffer, res })
-  }
 }
diff --git a/core/base-service/base.spec.js b/core/base-service/base.spec.js
index 8721ab03dd3f51438c83e892b7cde88c82b63986..274daf6ece1d2d75f52071440308cccac9b5a16e 100644
--- a/core/base-service/base.spec.js
+++ b/core/base-service/base.spec.js
@@ -25,22 +25,16 @@ const queryParamSchema = Joi.object({
   .required()
 
 class DummyService extends BaseService {
-  static render({ namedParamA, queryParamA }) {
-    return {
-      message: `Hello namedParamA: ${namedParamA} with queryParamA: ${queryParamA}`,
-    }
-  }
-
-  async handle({ namedParamA }, { queryParamA }) {
-    return this.constructor.render({ namedParamA, queryParamA })
-  }
-
   static get category() {
     return 'other'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'cat', namedLogo: 'appveyor' }
+  static get route() {
+    return {
+      base: 'foo',
+      pattern: ':namedParamA',
+      queryParamSchema,
+    }
   }
 
   static get examples() {
@@ -54,13 +48,19 @@ class DummyService extends BaseService {
     ]
   }
 
-  static get route() {
+  static get defaultBadgeData() {
+    return { label: 'cat', namedLogo: 'appveyor' }
+  }
+
+  static render({ namedParamA, queryParamA }) {
     return {
-      base: 'foo',
-      pattern: ':namedParamA',
-      queryParamSchema,
+      message: `Hello namedParamA: ${namedParamA} with queryParamA: ${queryParamA}`,
     }
   }
+
+  async handle({ namedParamA }, { queryParamA }) {
+    return this.constructor.render({ namedParamA, queryParamA })
+  }
 }
 
 describe('BaseService', function() {
diff --git a/core/base-service/deprecated-service.js b/core/base-service/deprecated-service.js
index c844070f28b12f87254d3d4e2154b1c6e87fb918..8358e1f0f1a78c9bcdccf21006ba7597b72abdd0 100644
--- a/core/base-service/deprecated-service.js
+++ b/core/base-service/deprecated-service.js
@@ -38,22 +38,22 @@ function deprecatedService(attrs) {
       return category
     }
 
-    static get route() {
-      return route
-    }
-
     static get isDeprecated() {
       return true
     }
 
-    static get defaultBadgeData() {
-      return { label }
+    static get route() {
+      return route
     }
 
     static get examples() {
       return examples
     }
 
+    static get defaultBadgeData() {
+      return { label }
+    }
+
     async handle() {
       throw new Deprecated({ prettyMessage: message })
     }
diff --git a/core/base-service/redirector.js b/core/base-service/redirector.js
index e738ce8352c3bc0656be268de464c96b046c0149..490296e4b6c065a257bf07992f2513f4e3ee75b5 100644
--- a/core/base-service/redirector.js
+++ b/core/base-service/redirector.js
@@ -40,18 +40,6 @@ module.exports = function redirector(attrs) {
   } = Joi.attempt(attrs, attrSchema, `Redirector for ${attrs.route.base}`)
 
   return class Redirector extends BaseService {
-    static get category() {
-      return category
-    }
-
-    static get route() {
-      return route
-    }
-
-    static get isDeprecated() {
-      return true
-    }
-
     static get name() {
       if (name) {
         return name
@@ -62,6 +50,18 @@ module.exports = function redirector(attrs) {
       }
     }
 
+    static get category() {
+      return category
+    }
+
+    static get isDeprecated() {
+      return true
+    }
+
+    static get route() {
+      return route
+    }
+
     static register({ camp, requestCounter }) {
       const { regex, captureNames } = prepareRoute(this.route)
 
diff --git a/package-lock.json b/package-lock.json
index 3999fb0b58b8902c7b6279f521f0b10a5de607c4..21d79f8fd6fc22694384d04cbd4fb5013e111df9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8977,6 +8977,12 @@
       "integrity": "sha512-lHBVRIaz5ibnIgNG07JNiAuBUeKhEf8l4etNx5vfAEwqQ5tcuK3jV9yjmopPgQDagQb7HwIuQVsE3IVcGrRnag==",
       "dev": true
     },
+    "eslint-plugin-sort-class-members": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-sort-class-members/-/eslint-plugin-sort-class-members-1.4.0.tgz",
+      "integrity": "sha512-FQG6d4Cy2vYmG9gr6J138E91WaltqwOk/b/7GCssPqnUmizrcgOeN91bV5eOTuoS4RSH1Jdn4ukWEtyWLwV8ig==",
+      "dev": true
+    },
     "eslint-plugin-standard": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz",
diff --git a/package.json b/package.json
index 532f9c5f9ce2192a4da2f2bf573ecd7778ce953f..e59898e8df9ea78054045efdb18bdd4a0b4bce92 100644
--- a/package.json
+++ b/package.json
@@ -164,6 +164,7 @@
     "eslint-plugin-promise": "^4.1.1",
     "eslint-plugin-react": "^7.12.4",
     "eslint-plugin-react-hooks": "^1.6.0",
+    "eslint-plugin-sort-class-members": "^1.4.0",
     "eslint-plugin-standard": "^4.0.0",
     "fetch-ponyfill": "^6.0.0",
     "fs-readfile-promise": "^3.0.1",
diff --git a/services/amo/amo-base.js b/services/amo/amo-base.js
index 3bb863f47004c1ed21085431c7717f12791f8507..394f4014cf078148babc4333dfb3799e2186e183 100644
--- a/services/amo/amo-base.js
+++ b/services/amo/amo-base.js
@@ -18,16 +18,16 @@ const schema = Joi.object({
 }).required()
 
 class BaseAmoService extends BaseJsonService {
+  static get defaultBadgeData() {
+    return { label: 'mozilla add-on' }
+  }
+
   async fetch({ addonId }) {
     return this._requestJson({
       schema,
       url: `https://addons.mozilla.org/api/v3/addons/addon/${addonId}`,
     })
   }
-
-  static get defaultBadgeData() {
-    return { label: 'mozilla add-on' }
-  }
 }
 
 module.exports = { BaseAmoService, keywords }
diff --git a/services/conda/conda-base.js b/services/conda/conda-base.js
index 01812ef460e2586abcb96f8cf2c51031f91e0023..897318af0354ddc375fc718268f4cb25a631af0e 100644
--- a/services/conda/conda-base.js
+++ b/services/conda/conda-base.js
@@ -19,14 +19,14 @@ const condaSchema = Joi.object({
 }).required()
 
 module.exports = class BaseCondaService extends BaseJsonService {
+  static get defaultBadgeData() {
+    return { label: 'conda' }
+  }
+
   async fetch({ channel, pkg }) {
     return this._requestJson({
       schema: condaSchema,
       url: `https://api.anaconda.org/package/${channel}/${pkg}`,
     })
   }
-
-  static get defaultBadgeData() {
-    return { label: 'conda' }
-  }
 }
diff --git a/services/powershellgallery/powershellgallery.service.js b/services/powershellgallery/powershellgallery.service.js
index e92df73f7dc00da2989e45985a140266d8f7224f..72541c861330626e206bed552bcbe19dbcaac801 100644
--- a/services/powershellgallery/powershellgallery.service.js
+++ b/services/powershellgallery/powershellgallery.service.js
@@ -33,12 +33,6 @@ class PowershellGalleryPlatformSupport extends BaseXmlService {
     return 'platform-support'
   }
 
-  static get defaultBadgeData() {
-    return {
-      label: 'platform',
-    }
-  }
-
   static get route() {
     return {
       base: 'powershellgallery/p',
@@ -58,6 +52,12 @@ class PowershellGalleryPlatformSupport extends BaseXmlService {
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'platform',
+    }
+  }
+
   static render({ platforms }) {
     return {
       message: platforms.join(' | '),
diff --git a/services/pub/pub.service.js b/services/pub/pub.service.js
index 2368c3952f5f644e13bf1f2aeb8b812f0cbd9258..52da8bdfd261efd7686fad1bd583948e10f5c9ca 100644
--- a/services/pub/pub.service.js
+++ b/services/pub/pub.service.js
@@ -22,10 +22,6 @@ module.exports = class PubVersion extends BaseJsonService {
     }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'pub' }
-  }
-
   static get examples() {
     return [
       {
@@ -45,6 +41,10 @@ module.exports = class PubVersion extends BaseJsonService {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'pub' }
+  }
+
   async fetch({ packageName }) {
     return this._requestJson({
       schema,
diff --git a/services/puppetforge/puppetforge-module-version.service.js b/services/puppetforge/puppetforge-module-version.service.js
index b083804bf4b65d566acb37bdbe6800a9d1c74354..14e5b90ae5afc027e0c73d583cfa8cf8d209a946 100644
--- a/services/puppetforge/puppetforge-module-version.service.js
+++ b/services/puppetforge/puppetforge-module-version.service.js
@@ -15,10 +15,6 @@ module.exports = class PuppetforgeModuleVersion extends BasePuppetForgeModulesSe
     }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'puppetforge' }
-  }
-
   static get examples() {
     return [
       {
@@ -32,6 +28,10 @@ module.exports = class PuppetforgeModuleVersion extends BasePuppetForgeModulesSe
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'puppetforge' }
+  }
+
   async handle({ user, moduleName }) {
     const data = await this.fetch({ user, moduleName })
     return renderVersionBadge({ version: data.current_release.version })
diff --git a/services/puppetforge/puppetforge-user-module-count.service.js b/services/puppetforge/puppetforge-user-module-count.service.js
index c9663ed6e983b33f0f5fe25aa20fc3de850838fb..3fd3f3cec39bacc9784502530cc7a5e6fb9959cb 100644
--- a/services/puppetforge/puppetforge-user-module-count.service.js
+++ b/services/puppetforge/puppetforge-user-module-count.service.js
@@ -9,10 +9,6 @@ module.exports = class PuppetForgeModuleCountService extends BasePuppetForgeUser
     return 'other'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'modules' }
-  }
-
   static get route() {
     return {
       base: 'puppetforge/mc',
@@ -32,9 +28,8 @@ module.exports = class PuppetForgeModuleCountService extends BasePuppetForgeUser
     ]
   }
 
-  async handle({ user }) {
-    const data = await this.fetch({ user })
-    return this.constructor.render({ modules: data.module_count })
+  static get defaultBadgeData() {
+    return { label: 'modules' }
   }
 
   static render({ modules }) {
@@ -43,4 +38,9 @@ module.exports = class PuppetForgeModuleCountService extends BasePuppetForgeUser
       color: floorCountColor(modules, 5, 10, 50),
     }
   }
+
+  async handle({ user }) {
+    const data = await this.fetch({ user })
+    return this.constructor.render({ modules: data.module_count })
+  }
 }
diff --git a/services/puppetforge/puppetforge-user-release-count.service.js b/services/puppetforge/puppetforge-user-release-count.service.js
index 43d14e749540183ce37808876cf806f0bbf4597d..babd938d16118cf61a70864d95bcc3f842f36685 100644
--- a/services/puppetforge/puppetforge-user-release-count.service.js
+++ b/services/puppetforge/puppetforge-user-release-count.service.js
@@ -9,10 +9,6 @@ module.exports = class PuppetForgeReleaseCountService extends BasePuppetForgeUse
     return 'other'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'releases' }
-  }
-
   static get route() {
     return {
       base: 'puppetforge/rc',
@@ -32,9 +28,8 @@ module.exports = class PuppetForgeReleaseCountService extends BasePuppetForgeUse
     ]
   }
 
-  async handle({ user }) {
-    const data = await this.fetch({ user })
-    return this.constructor.render({ releases: data.release_count })
+  static get defaultBadgeData() {
+    return { label: 'releases' }
   }
 
   static render({ releases }) {
@@ -43,4 +38,9 @@ module.exports = class PuppetForgeReleaseCountService extends BasePuppetForgeUse
       color: floorCountColor(releases, 10, 50, 100),
     }
   }
+
+  async handle({ user }) {
+    const data = await this.fetch({ user })
+    return this.constructor.render({ releases: data.release_count })
+  }
 }
diff --git a/services/pypi/pypi-djversions.service.js b/services/pypi/pypi-djversions.service.js
index 77399444b706ca4915fc3ae58c0716accb2c4b76..d2ab1e54d038fd6bb6d7e0080e463082d888767c 100644
--- a/services/pypi/pypi-djversions.service.js
+++ b/services/pypi/pypi-djversions.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiDjangoVersions extends PypiBase {
     return this.buildRoute('pypi/djversions')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'django versions' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiDjangoVersions extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'django versions' }
+  }
+
   static render({ versions }) {
     if (versions.length > 0) {
       return {
diff --git a/services/pypi/pypi-downloads.service.js b/services/pypi/pypi-downloads.service.js
index 6cd768d69dbbe218e84aa0591ceea3cc31b15f5d..617a62b6c1908a0d9efe2ff98d3aa189c4bc8580 100644
--- a/services/pypi/pypi-downloads.service.js
+++ b/services/pypi/pypi-downloads.service.js
@@ -34,33 +34,6 @@ const periodMap = {
 // this badge uses PyPI Stats instead of the PyPI API
 // so it doesn't extend PypiBase
 module.exports = class PypiDownloads extends BaseJsonService {
-  async fetch({ packageName }) {
-    return this._requestJson({
-      url: `https://pypistats.org/api/packages/${packageName.toLowerCase()}/recent`,
-      schema,
-      errorMessages: { 404: 'package not found' },
-    })
-  }
-
-  static render({ period, downloads }) {
-    return {
-      message: `${metric(downloads)}${periodMap[period].suffix}`,
-      color: downloadCount(downloads),
-    }
-  }
-
-  async handle({ period, packageName }) {
-    const json = await this.fetch({ packageName })
-    return this.constructor.render({
-      period,
-      downloads: json.data[periodMap[period].api_field],
-    })
-  }
-
-  static get defaultBadgeData() {
-    return { label: 'downloads' }
-  }
-
   static get category() {
     return 'downloads'
   }
@@ -85,4 +58,31 @@ module.exports = class PypiDownloads extends BaseJsonService {
       },
     ]
   }
+
+  static get defaultBadgeData() {
+    return { label: 'downloads' }
+  }
+
+  static render({ period, downloads }) {
+    return {
+      message: `${metric(downloads)}${periodMap[period].suffix}`,
+      color: downloadCount(downloads),
+    }
+  }
+
+  async fetch({ packageName }) {
+    return this._requestJson({
+      url: `https://pypistats.org/api/packages/${packageName.toLowerCase()}/recent`,
+      schema,
+      errorMessages: { 404: 'package not found' },
+    })
+  }
+
+  async handle({ period, packageName }) {
+    const json = await this.fetch({ packageName })
+    return this.constructor.render({
+      period,
+      downloads: json.data[periodMap[period].api_field],
+    })
+  }
 }
diff --git a/services/pypi/pypi-format.service.js b/services/pypi/pypi-format.service.js
index 2dc514c69772a8d54d79f24ea33339ac5299b069..ea64f04271ddb1add4e8d71310548772a20ab653 100644
--- a/services/pypi/pypi-format.service.js
+++ b/services/pypi/pypi-format.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiFormat extends PypiBase {
     return this.buildRoute('pypi/format')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'format' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiFormat extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'format' }
+  }
+
   static render({ hasWheel, hasEgg }) {
     if (hasWheel) {
       return {
diff --git a/services/pypi/pypi-implementation.service.js b/services/pypi/pypi-implementation.service.js
index 659a581b0243110b0688e8ea73b491a23ff46d87..1fd33a4d30789f81ab381cf5e5ef40eca7cad31a 100644
--- a/services/pypi/pypi-implementation.service.js
+++ b/services/pypi/pypi-implementation.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiImplementation extends PypiBase {
     return this.buildRoute('pypi/implementation')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'implementation' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiImplementation extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'implementation' }
+  }
+
   static render({ implementations }) {
     return {
       message: implementations.sort().join(' | '),
diff --git a/services/pypi/pypi-pyversions.service.js b/services/pypi/pypi-pyversions.service.js
index ff559c4b700159ed9eaf6ebfadc13b13378870a9..8a4b4168ac531d760a564653956f31a6ebf73230 100644
--- a/services/pypi/pypi-pyversions.service.js
+++ b/services/pypi/pypi-pyversions.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiPythonVersions extends PypiBase {
     return this.buildRoute('pypi/pyversions')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'python' }
-  }
-
   static get examples() {
     return [
       {
@@ -27,6 +23,10 @@ module.exports = class PypiPythonVersions extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'python' }
+  }
+
   static render({ versions }) {
     const versionSet = new Set(versions)
     // We only show v2 if eg. v2.4 does not appear.
diff --git a/services/pypi/pypi-status.service.js b/services/pypi/pypi-status.service.js
index 9b1385a2771d7f2264b0b1a6f1d8d9f4224d9a41..0ae484a3681d1c77f3b1e4c53e36f1e27294bf10 100644
--- a/services/pypi/pypi-status.service.js
+++ b/services/pypi/pypi-status.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiStatus extends PypiBase {
     return this.buildRoute('pypi/status')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'status' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiStatus extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'status' }
+  }
+
   static render({ status = '' }) {
     status = status.toLowerCase()
 
diff --git a/services/pypi/pypi-version.service.js b/services/pypi/pypi-version.service.js
index cee37daafc2e5eeee258121f89cd564cf550fd16..271adfe6ebfb95fc7a10d40d3f48bccaf9f378c8 100644
--- a/services/pypi/pypi-version.service.js
+++ b/services/pypi/pypi-version.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiVersion extends PypiBase {
     return this.buildRoute('pypi/v')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'pypi' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiVersion extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'pypi' }
+  }
+
   static render({ version }) {
     return renderVersionBadge({ version })
   }
diff --git a/services/pypi/pypi-wheel.service.js b/services/pypi/pypi-wheel.service.js
index 3c0367cac2a51520a51574a64e459a58bc997068..91a5b448aed29f993fefe38f3ef54746cf8b8ed7 100644
--- a/services/pypi/pypi-wheel.service.js
+++ b/services/pypi/pypi-wheel.service.js
@@ -12,10 +12,6 @@ module.exports = class PypiWheel extends PypiBase {
     return this.buildRoute('pypi/wheel')
   }
 
-  static get defaultBadgeData() {
-    return { label: 'wheel' }
-  }
-
   static get examples() {
     return [
       {
@@ -28,6 +24,10 @@ module.exports = class PypiWheel extends PypiBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'wheel' }
+  }
+
   static render({ hasWheel }) {
     if (hasWheel) {
       return {
diff --git a/services/redmine/redmine.service.js b/services/redmine/redmine.service.js
index 9f7b0974c307ea3f0ad16b2c38b020767771ad69..03645746623d5991abe8b6a1e563508d3bec9585 100644
--- a/services/redmine/redmine.service.js
+++ b/services/redmine/redmine.service.js
@@ -14,11 +14,6 @@ const schema = Joi.object({
 })
 
 class BaseRedminePluginRating extends BaseXmlService {
-  async fetch({ plugin }) {
-    const url = `https://www.redmine.org/plugins/${plugin}.xml`
-    return this._requestXml({ schema, url })
-  }
-
   static get category() {
     return 'rating'
   }
@@ -27,6 +22,11 @@ class BaseRedminePluginRating extends BaseXmlService {
     throw new Error(`render() function not implemented for ${this.name}`)
   }
 
+  async fetch({ plugin }) {
+    const url = `https://www.redmine.org/plugins/${plugin}.xml`
+    return this._requestXml({ schema, url })
+  }
+
   async handle({ plugin }) {
     const data = await this.fetch({ plugin })
     const rating = data['redmine-plugin']['ratings-average']
@@ -42,10 +42,6 @@ class RedminePluginRating extends BaseRedminePluginRating {
     }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'redmine' }
-  }
-
   static get examples() {
     return [
       {
@@ -56,6 +52,10 @@ class RedminePluginRating extends BaseRedminePluginRating {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'redmine' }
+  }
+
   static render({ rating }) {
     return {
       label: 'rating',
diff --git a/services/requires/requires.service.js b/services/requires/requires.service.js
index cd04a5032af00a4f76736eb5ab6a93572c06158a..5e8ea1a0947ad4e47d2af6aeeba3bcb8b3d9cdda 100644
--- a/services/requires/requires.service.js
+++ b/services/requires/requires.service.js
@@ -8,6 +8,10 @@ const statusSchema = Joi.object({
 }).required()
 
 module.exports = class RequiresIo extends BaseJsonService {
+  static get category() {
+    return 'dependencies'
+  }
+
   static get route() {
     return {
       base: 'requires',
@@ -15,42 +19,6 @@ module.exports = class RequiresIo extends BaseJsonService {
     }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'requirements' }
-  }
-
-  async handle({ service, user, repo, branch }) {
-    const { status } = await this.fetch({ service, user, repo, branch })
-    return this.constructor.render({ status })
-  }
-
-  async fetch({ service, user, repo, branch }) {
-    const url = `https://requires.io/api/v1/status/${service}/${user}/${repo}`
-    return this._requestJson({
-      url,
-      schema: statusSchema,
-      options: { qs: { branch } },
-    })
-  }
-
-  static render({ status }) {
-    let message = status
-    let color = 'lightgrey'
-    if (status === 'up-to-date') {
-      message = 'up to date'
-      color = 'brightgreen'
-    } else if (status === 'outdated') {
-      color = 'yellow'
-    } else if (status === 'insecure') {
-      color = 'red'
-    }
-    return { message, color }
-  }
-
-  static get category() {
-    return 'dependencies'
-  }
-
   static get examples() {
     return [
       {
@@ -72,4 +40,36 @@ module.exports = class RequiresIo extends BaseJsonService {
       },
     ]
   }
+
+  static get defaultBadgeData() {
+    return { label: 'requirements' }
+  }
+
+  static render({ status }) {
+    let message = status
+    let color = 'lightgrey'
+    if (status === 'up-to-date') {
+      message = 'up to date'
+      color = 'brightgreen'
+    } else if (status === 'outdated') {
+      color = 'yellow'
+    } else if (status === 'insecure') {
+      color = 'red'
+    }
+    return { message, color }
+  }
+
+  async fetch({ service, user, repo, branch }) {
+    const url = `https://requires.io/api/v1/status/${service}/${user}/${repo}`
+    return this._requestJson({
+      url,
+      schema: statusSchema,
+      options: { qs: { branch } },
+    })
+  }
+
+  async handle({ service, user, repo, branch }) {
+    const { status } = await this.fetch({ service, user, repo, branch })
+    return this.constructor.render({ status })
+  }
 }
diff --git a/services/sonar/sonar-base.js b/services/sonar/sonar-base.js
index b25afc2e791469cc64a9a87d7f79d32570bbd876..d7bf177d26f7d441d699f99d6418e3dd822b0a51 100644
--- a/services/sonar/sonar-base.js
+++ b/services/sonar/sonar-base.js
@@ -40,17 +40,6 @@ const legacyApiSchema = Joi.array()
   .required()
 
 module.exports = class SonarBase extends BaseJsonService {
-  transform({ json, sonarVersion }) {
-    const useLegacyApi = isLegacyVersion({ sonarVersion })
-    const rawValue = useLegacyApi
-      ? json[0].msr[0].val
-      : json.component.measures[0].value
-    const value = parseInt(rawValue)
-
-    // Most values are numeric, but not all of them.
-    return { metricValue: value || rawValue }
-  }
-
   async fetch({ sonarVersion, protocol, host, component, metricName }) {
     let qs, url
     const useLegacyApi = isLegacyVersion({ sonarVersion })
@@ -88,4 +77,15 @@ module.exports = class SonarBase extends BaseJsonService {
       },
     })
   }
+
+  transform({ json, sonarVersion }) {
+    const useLegacyApi = isLegacyVersion({ sonarVersion })
+    const rawValue = useLegacyApi
+      ? json[0].msr[0].val
+      : json.component.measures[0].value
+    const value = parseInt(rawValue)
+
+    // Most values are numeric, but not all of them.
+    return { metricValue: value || rawValue }
+  }
 }
diff --git a/services/stackexchange/stackexchange-monthlyquestions.service.js b/services/stackexchange/stackexchange-monthlyquestions.service.js
index 2639319a02806cb1b47af219de5b4a38b5623d66..afe7a7fadbf93cefde08198034b240b36293b899 100644
--- a/services/stackexchange/stackexchange-monthlyquestions.service.js
+++ b/services/stackexchange/stackexchange-monthlyquestions.service.js
@@ -16,8 +16,11 @@ module.exports = class StackExchangeMonthlyQuestions extends BaseJsonService {
     return 'chat'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'stackoverflow' }
+  static get route() {
+    return {
+      base: 'stackexchange',
+      pattern: ':stackexchangesite/qm/:query',
+    }
   }
 
   static get examples() {
@@ -35,11 +38,8 @@ module.exports = class StackExchangeMonthlyQuestions extends BaseJsonService {
     ]
   }
 
-  static get route() {
-    return {
-      base: 'stackexchange',
-      pattern: ':stackexchangesite/qm/:query',
-    }
+  static get defaultBadgeData() {
+    return { label: 'stackoverflow' }
   }
 
   static render(props) {
diff --git a/services/stackexchange/stackexchange-reputation.service.js b/services/stackexchange/stackexchange-reputation.service.js
index 597fd445275882ebf6d22c94a47aef2ef3f67ba2..fd7d6adf57930d8ee21e3b309b0f37905834dd96 100644
--- a/services/stackexchange/stackexchange-reputation.service.js
+++ b/services/stackexchange/stackexchange-reputation.service.js
@@ -30,10 +30,6 @@ module.exports = class StackExchangeReputation extends BaseJsonService {
     }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'stackoverflow' }
-  }
-
   static get examples() {
     return [
       {
@@ -48,6 +44,10 @@ module.exports = class StackExchangeReputation extends BaseJsonService {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'stackoverflow' }
+  }
+
   static render({ stackexchangesite, numValue }) {
     const label = `${stackexchangesite} reputation`
 
diff --git a/services/stackexchange/stackexchange-taginfo.service.js b/services/stackexchange/stackexchange-taginfo.service.js
index 6281b77966f64c4fca19f1a8c57722d636e51754..254591fab5ee8cdc6c0d566505ecc3b605d874bf 100644
--- a/services/stackexchange/stackexchange-taginfo.service.js
+++ b/services/stackexchange/stackexchange-taginfo.service.js
@@ -22,8 +22,11 @@ module.exports = class StackExchangeQuestions extends BaseJsonService {
     return 'chat'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'stackoverflow' }
+  static get route() {
+    return {
+      base: 'stackexchange',
+      pattern: ':stackexchangesite/t/:query',
+    }
   }
 
   static get examples() {
@@ -41,11 +44,8 @@ module.exports = class StackExchangeQuestions extends BaseJsonService {
     ]
   }
 
-  static get route() {
-    return {
-      base: 'stackexchange',
-      pattern: ':stackexchangesite/t/:query',
-    }
+  static get defaultBadgeData() {
+    return { label: 'stackoverflow' }
   }
 
   static render(props) {
diff --git a/services/steam/steam-workshop.service.js b/services/steam/steam-workshop.service.js
index 608086159f45c2501fc0e3f6b97c52246325d149..360aad3d68494f33ef7cd05d3e81f92c038ce1a4 100644
--- a/services/steam/steam-workshop.service.js
+++ b/services/steam/steam-workshop.service.js
@@ -121,6 +121,36 @@ const fileFoundOrNotSchema = Joi.alternatives(
 )
 
 class SteamCollectionSize extends BaseSteamAPI {
+  static get category() {
+    return 'other'
+  }
+
+  static get route() {
+    return {
+      base: 'steam/collection-files',
+      pattern: ':collectionId',
+    }
+  }
+
+  static get examples() {
+    return [
+      {
+        title: 'Steam Collection Files',
+        namedParams: { collectionId: '180077636' },
+        staticPreview: this.render({ size: 32 }),
+        documentation,
+      },
+    ]
+  }
+
+  static get defaultBadgeData() {
+    return { label: 'files' }
+  }
+
+  static render({ size }) {
+    return { message: metric(size), color: 'brightgreen' }
+  }
+
   static get interf() {
     return 'ISteamRemoteStorage'
   }
@@ -133,10 +163,6 @@ class SteamCollectionSize extends BaseSteamAPI {
     return '1'
   }
 
-  static render({ size }) {
-    return { message: metric(size), color: 'brightgreen' }
-  }
-
   async handle({ collectionId }) {
     const options = {
       method: 'POST',
@@ -159,32 +185,6 @@ class SteamCollectionSize extends BaseSteamAPI {
       size: json.response.collectiondetails[0].children.length,
     })
   }
-
-  static get category() {
-    return 'other'
-  }
-
-  static get defaultBadgeData() {
-    return { label: 'files' }
-  }
-
-  static get route() {
-    return {
-      base: 'steam/collection-files',
-      pattern: ':collectionId',
-    }
-  }
-
-  static get examples() {
-    return [
-      {
-        title: 'Steam Collection Files',
-        namedParams: { collectionId: '180077636' },
-        staticPreview: this.render({ size: 32 }),
-        documentation,
-      },
-    ]
-  }
 }
 
 class SteamFileService extends BaseSteamAPI {
@@ -200,6 +200,10 @@ class SteamFileService extends BaseSteamAPI {
     return '1'
   }
 
+  async onRequest({ response }) {
+    throw new Error(`onRequest() wasn't implemented for ${this.name}`)
+  }
+
   async handle({ fileId }) {
     const options = {
       method: 'POST',
@@ -217,29 +221,13 @@ class SteamFileService extends BaseSteamAPI {
 
     return this.onRequest({ response: json.response.publishedfiledetails[0] })
   }
-
-  async onRequest({ response }) {
-    throw new Error(`onRequest() wasn't implemented for ${this.name}`)
-  }
 }
 
 class SteamFileSize extends SteamFileService {
-  static render({ fileSize }) {
-    return { message: prettyBytes(fileSize), color: 'brightgreen' }
-  }
-
-  async onRequest({ response }) {
-    return this.constructor.render({ fileSize: response.file_size })
-  }
-
   static get category() {
     return 'size'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'size' }
-  }
-
   static get route() {
     return {
       base: 'steam/size',
@@ -257,20 +245,23 @@ class SteamFileSize extends SteamFileService {
       },
     ]
   }
-}
 
-class SteamFileReleaseDate extends SteamFileService {
-  static render({ releaseDate }) {
-    return { message: formatDate(releaseDate), color: ageColor(releaseDate) }
+  static get defaultBadgeData() {
+    return { label: 'size' }
+  }
+
+  static render({ fileSize }) {
+    return { message: prettyBytes(fileSize), color: 'brightgreen' }
   }
 
   async onRequest({ response }) {
-    const releaseDate = new Date(0).setUTCSeconds(response.time_created)
-    return this.constructor.render({ releaseDate })
+    return this.constructor.render({ fileSize: response.file_size })
   }
+}
 
-  static get defaultBadgeData() {
-    return { label: 'release date' }
+class SteamFileReleaseDate extends SteamFileService {
+  static get category() {
+    return 'activity'
   }
 
   static get route() {
@@ -293,24 +284,21 @@ class SteamFileReleaseDate extends SteamFileService {
     ]
   }
 
-  static get category() {
-    return 'activity'
+  static get defaultBadgeData() {
+    return { label: 'release date' }
   }
-}
 
-class SteamFileSubscriptions extends SteamFileService {
-  static render({ subscriptions }) {
-    return { message: metric(subscriptions), color: 'brightgreen' }
+  static render({ releaseDate }) {
+    return { message: formatDate(releaseDate), color: ageColor(releaseDate) }
   }
 
   async onRequest({ response }) {
-    return this.constructor.render({ subscriptions: response.subscriptions })
-  }
-
-  static get defaultBadgeData() {
-    return { label: 'subscriptions' }
+    const releaseDate = new Date(0).setUTCSeconds(response.time_created)
+    return this.constructor.render({ releaseDate })
   }
+}
 
+class SteamFileSubscriptions extends SteamFileService {
   static get category() {
     return 'rating'
   }
@@ -332,21 +320,21 @@ class SteamFileSubscriptions extends SteamFileService {
       },
     ]
   }
-}
 
-class SteamFileFavorites extends SteamFileService {
-  static render({ favorites }) {
-    return { message: metric(favorites), color: 'brightgreen' }
+  static get defaultBadgeData() {
+    return { label: 'subscriptions' }
   }
 
-  async onRequest({ response }) {
-    return this.constructor.render({ favorites: response.favorited })
+  static render({ subscriptions }) {
+    return { message: metric(subscriptions), color: 'brightgreen' }
   }
 
-  static get defaultBadgeData() {
-    return { label: 'favorites' }
+  async onRequest({ response }) {
+    return this.constructor.render({ subscriptions: response.subscriptions })
   }
+}
 
+class SteamFileFavorites extends SteamFileService {
   static get category() {
     return 'rating'
   }
@@ -368,27 +356,25 @@ class SteamFileFavorites extends SteamFileService {
       },
     ]
   }
-}
 
-class SteamFileDownloads extends SteamFileService {
-  static render({ downloads }) {
-    return { message: metric(downloads), color: downloadCount(downloads) }
+  static get defaultBadgeData() {
+    return { label: 'favorites' }
+  }
+
+  static render({ favorites }) {
+    return { message: metric(favorites), color: 'brightgreen' }
   }
 
   async onRequest({ response }) {
-    return this.constructor.render({
-      downloads: response.lifetime_subscriptions,
-    })
+    return this.constructor.render({ favorites: response.favorited })
   }
+}
 
+class SteamFileDownloads extends SteamFileService {
   static get category() {
     return 'downloads'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'downloads' }
-  }
-
   static get route() {
     return {
       base: 'steam/downloads',
@@ -406,19 +392,25 @@ class SteamFileDownloads extends SteamFileService {
       },
     ]
   }
-}
 
-class SteamFileViews extends SteamFileService {
-  static render({ views }) {
-    return { message: metric(views), color: 'brightgreen' }
+  static get defaultBadgeData() {
+    return { label: 'downloads' }
+  }
+
+  static render({ downloads }) {
+    return { message: metric(downloads), color: downloadCount(downloads) }
   }
 
   async onRequest({ response }) {
-    return this.constructor.render({ views: response.views })
+    return this.constructor.render({
+      downloads: response.lifetime_subscriptions,
+    })
   }
+}
 
-  static get defaultBadgeData() {
-    return { label: 'views' }
+class SteamFileViews extends SteamFileService {
+  static get category() {
+    return 'other'
   }
 
   static get route() {
@@ -439,8 +431,16 @@ class SteamFileViews extends SteamFileService {
     ]
   }
 
-  static get category() {
-    return 'other'
+  static get defaultBadgeData() {
+    return { label: 'views' }
+  }
+
+  static render({ views }) {
+    return { message: metric(views), color: 'brightgreen' }
+  }
+
+  async onRequest({ response }) {
+    return this.constructor.render({ views: response.views })
   }
 }
 
diff --git a/services/swagger/swagger.service.js b/services/swagger/swagger.service.js
index 904ad537f40898e088399beb9fd91c0ff3e32608..f084048dd46c633df93ddd4bc4bc792163d8c344 100644
--- a/services/swagger/swagger.service.js
+++ b/services/swagger/swagger.service.js
@@ -15,8 +15,8 @@ const validatorSchema = Joi.object()
   .required()
 
 module.exports = class SwaggerValidatorService extends BaseJsonService {
-  static render({ message, clr }) {
-    return { message, color: clr }
+  static get category() {
+    return 'other'
   }
 
   static get route() {
@@ -26,19 +26,27 @@ module.exports = class SwaggerValidatorService extends BaseJsonService {
     }
   }
 
+  static get examples() {
+    return [
+      {
+        title: 'Swagger Validator',
+        pattern: ':scheme/:url',
+        staticPreview: this.render({ message: 'valid', clr: 'brightgreen' }),
+        namedParams: {
+          scheme: 'https',
+          url:
+            'raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore-expanded.json',
+        },
+      },
+    ]
+  }
+
   static get defaultBadgeData() {
     return { label: 'swagger' }
   }
 
-  async handle({ scheme, url }) {
-    const json = await this.fetch({ scheme, urlF: url })
-    const valMessages = json.schemaValidationMessages
-
-    if (!valMessages || valMessages.length === 0) {
-      return this.constructor.render({ message: 'valid', clr: 'brightgreen' })
-    } else {
-      return this.constructor.render({ message: 'invalid', clr: 'red' })
-    }
+  static render({ message, clr }) {
+    return { message, color: clr }
   }
 
   async fetch({ scheme, urlF }) {
@@ -54,22 +62,14 @@ module.exports = class SwaggerValidatorService extends BaseJsonService {
     })
   }
 
-  static get category() {
-    return 'other'
-  }
+  async handle({ scheme, url }) {
+    const json = await this.fetch({ scheme, urlF: url })
+    const valMessages = json.schemaValidationMessages
 
-  static get examples() {
-    return [
-      {
-        title: 'Swagger Validator',
-        pattern: ':scheme/:url',
-        staticPreview: this.render({ message: 'valid', clr: 'brightgreen' }),
-        namedParams: {
-          scheme: 'https',
-          url:
-            'raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v2.0/json/petstore-expanded.json',
-        },
-      },
-    ]
+    if (!valMessages || valMessages.length === 0) {
+      return this.constructor.render({ message: 'valid', clr: 'brightgreen' })
+    } else {
+      return this.constructor.render({ message: 'invalid', clr: 'red' })
+    }
   }
 }
diff --git a/services/symfony/symfony-insight-base.js b/services/symfony/symfony-insight-base.js
index 3ba6b642a226699bfbe6b66ad6d92acd227e073c..3305fced6cc02f91d9f1eef58722bb752ca18033 100644
--- a/services/symfony/symfony-insight-base.js
+++ b/services/symfony/symfony-insight-base.js
@@ -47,16 +47,16 @@ const gradeColors = {
 }
 
 class SymfonyInsightBase extends BaseXmlService {
+  static get category() {
+    return 'analysis'
+  }
+
   static get defaultBadgeData() {
     return {
       label: 'symfony insight',
     }
   }
 
-  static get category() {
-    return 'analysis'
-  }
-
   async fetch({ projectUuid }) {
     const url = `https://insight.symfony.com/api/projects/${projectUuid}`
     const options = {
diff --git a/services/symfony/symfony-insight-grade.service.js b/services/symfony/symfony-insight-grade.service.js
index 92952f804b7af715307ae4a16c9bab3352c47853..b5b211d20a40e0afb2fa307f2713f9fce86d5272 100644
--- a/services/symfony/symfony-insight-grade.service.js
+++ b/services/symfony/symfony-insight-grade.service.js
@@ -7,24 +7,6 @@ const {
 } = require('./symfony-insight-base')
 
 module.exports = class SymfonyInsightGrade extends SymfonyInsightBase {
-  static render({ status, grade }) {
-    const label = 'grade'
-    if (status !== 'finished' && status !== '') {
-      return {
-        label,
-        message: 'pending',
-        color: 'lightgrey',
-      }
-    }
-
-    const message = grade === 'none' ? 'no medal' : grade
-    return {
-      label,
-      message,
-      color: gradeColors[grade],
-    }
-  }
-
   static get route() {
     return {
       base: 'symfony/i/grade',
@@ -48,6 +30,24 @@ module.exports = class SymfonyInsightGrade extends SymfonyInsightBase {
     ]
   }
 
+  static render({ status, grade }) {
+    const label = 'grade'
+    if (status !== 'finished' && status !== '') {
+      return {
+        label,
+        message: 'pending',
+        color: 'lightgrey',
+      }
+    }
+
+    const message = grade === 'none' ? 'no medal' : grade
+    return {
+      label,
+      message,
+      color: gradeColors[grade],
+    }
+  }
+
   async handle({ projectUuid }) {
     const data = await this.fetch({ projectUuid })
     const { grade, status } = this.transform({ data })
diff --git a/services/symfony/symfony-insight-stars.service.js b/services/symfony/symfony-insight-stars.service.js
index a66eac4ca2523bd064f81039414a36a030bb82b5..38470f455e748b92888f08f2f60b0136e27565e3 100644
--- a/services/symfony/symfony-insight-stars.service.js
+++ b/services/symfony/symfony-insight-stars.service.js
@@ -16,23 +16,6 @@ const gradeStars = {
 }
 
 module.exports = class SymfonyInsightStars extends SymfonyInsightBase {
-  static render({ status, grade }) {
-    const label = 'stars'
-    if (status !== 'finished' && status !== '') {
-      return {
-        label,
-        message: 'pending',
-        color: 'lightgrey',
-      }
-    }
-    const numStars = gradeStars[grade]
-    return {
-      label,
-      message: starRating(numStars, 4),
-      color: gradeColors[grade],
-    }
-  }
-
   static get route() {
     return {
       base: 'symfony/i/stars',
@@ -56,6 +39,23 @@ module.exports = class SymfonyInsightStars extends SymfonyInsightBase {
     ]
   }
 
+  static render({ status, grade }) {
+    const label = 'stars'
+    if (status !== 'finished' && status !== '') {
+      return {
+        label,
+        message: 'pending',
+        color: 'lightgrey',
+      }
+    }
+    const numStars = gradeStars[grade]
+    return {
+      label,
+      message: starRating(numStars, 4),
+      color: gradeColors[grade],
+    }
+  }
+
   async handle({ projectUuid }) {
     const data = await this.fetch({ projectUuid })
     const { grade, status } = this.transform({ data })
diff --git a/services/symfony/symfony-insight-violations.service.js b/services/symfony/symfony-insight-violations.service.js
index bee3720dd7eeef9f1ea67832446a12a058311541..270506502794b8e889e5649816c9851af6a5e437 100644
--- a/services/symfony/symfony-insight-violations.service.js
+++ b/services/symfony/symfony-insight-violations.service.js
@@ -3,6 +3,29 @@
 const { SymfonyInsightBase, keywords } = require('./symfony-insight-base')
 
 module.exports = class SymfonyInsightViolations extends SymfonyInsightBase {
+  static get route() {
+    return {
+      base: 'symfony/i/violations',
+      pattern: ':projectUuid',
+    }
+  }
+
+  static get examples() {
+    return [
+      {
+        title: 'SymfonyInsight Violations',
+        namedParams: {
+          projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
+        },
+        staticPreview: this.render({
+          numViolations: 0,
+          status: 'finished',
+        }),
+        keywords,
+      },
+    ]
+  }
+
   static render({
     status,
     numViolations,
@@ -54,29 +77,6 @@ module.exports = class SymfonyInsightViolations extends SymfonyInsightBase {
     }
   }
 
-  static get route() {
-    return {
-      base: 'symfony/i/violations',
-      pattern: ':projectUuid',
-    }
-  }
-
-  static get examples() {
-    return [
-      {
-        title: 'SymfonyInsight Violations',
-        namedParams: {
-          projectUuid: '45afb680-d4e6-4e66-93ea-bcfa79eb8a87',
-        },
-        staticPreview: this.render({
-          numViolations: 0,
-          status: 'finished',
-        }),
-        keywords,
-      },
-    ]
-  }
-
   async handle({ projectUuid }) {
     const data = await this.fetch({ projectUuid })
     const lastAnalysis = this.transform({ data })
diff --git a/services/teamcity/teamcity-build.service.js b/services/teamcity/teamcity-build.service.js
index 52f20876501e71ad6c6f790b6069cfc37540213e..f3e7e8fb4a9964b78dee2cf5266ad17ec0c858a9 100644
--- a/services/teamcity/teamcity-build.service.js
+++ b/services/teamcity/teamcity-build.service.js
@@ -15,31 +15,6 @@ const buildStatusSchema = Joi.object({
 }).required()
 
 module.exports = class TeamCityBuild extends TeamCityBase {
-  static render({ status, statusText, useVerbose }) {
-    if (status === 'SUCCESS') {
-      return {
-        message: 'passing',
-        color: 'brightgreen',
-      }
-    } else if (statusText && useVerbose) {
-      return {
-        message: statusText.toLowerCase(),
-        color: 'red',
-      }
-    } else {
-      return {
-        message: status.toLowerCase(),
-        color: 'red',
-      }
-    }
-  }
-
-  static get defaultBadgeData() {
-    return {
-      label: 'build',
-    }
-  }
-
   static get category() {
     return 'build'
   }
@@ -94,6 +69,31 @@ module.exports = class TeamCityBuild extends TeamCityBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'build',
+    }
+  }
+
+  static render({ status, statusText, useVerbose }) {
+    if (status === 'SUCCESS') {
+      return {
+        message: 'passing',
+        color: 'brightgreen',
+      }
+    } else if (statusText && useVerbose) {
+      return {
+        message: statusText.toLowerCase(),
+        color: 'red',
+      }
+    } else {
+      return {
+        message: status.toLowerCase(),
+        color: 'red',
+      }
+    }
+  }
+
   async handle({ protocol, hostAndPath, verbosity, buildId }) {
     // JetBrains Docs: https://confluence.jetbrains.com/display/TCD18/REST+API#RESTAPI-BuildStatusIcon
     const buildLocator = `buildType:(id:${buildId})`
diff --git a/services/teamcity/teamcity-coverage.service.js b/services/teamcity/teamcity-coverage.service.js
index f89d1e81339d2f5cfa61e19375dd4d0d030adf83..dc41fea87b8f51f5a9a30d88d40268180841c6b1 100644
--- a/services/teamcity/teamcity-coverage.service.js
+++ b/services/teamcity/teamcity-coverage.service.js
@@ -17,19 +17,6 @@ const buildStatisticsSchema = Joi.object({
 }).required()
 
 module.exports = class TeamCityCoverage extends TeamCityBase {
-  static render({ coverage }) {
-    return {
-      message: `${coverage.toFixed(0)}%`,
-      color: coveragePercentage(coverage),
-    }
-  }
-
-  static get defaultBadgeData() {
-    return {
-      label: 'coverage',
-    }
-  }
-
   static get category() {
     return 'coverage'
   }
@@ -69,21 +56,17 @@ module.exports = class TeamCityCoverage extends TeamCityBase {
     ]
   }
 
-  async handle({ protocol, hostAndPath, buildId }) {
-    // JetBrains Docs: https://confluence.jetbrains.com/display/TCD18/REST+API#RESTAPI-Statistics
-    const buildLocator = `buildType:(id:${buildId})`
-    const apiPath = `app/rest/builds/${encodeURIComponent(
-      buildLocator
-    )}/statistics`
-    const data = await this.fetch({
-      protocol,
-      hostAndPath,
-      apiPath,
-      schema: buildStatisticsSchema,
-    })
+  static get defaultBadgeData() {
+    return {
+      label: 'coverage',
+    }
+  }
 
-    const { coverage } = this.transform({ data })
-    return this.constructor.render({ coverage })
+  static render({ coverage }) {
+    return {
+      message: `${coverage.toFixed(0)}%`,
+      color: coveragePercentage(coverage),
+    }
   }
 
   transform({ data }) {
@@ -104,4 +87,21 @@ module.exports = class TeamCityCoverage extends TeamCityBase {
 
     throw new InvalidResponse({ prettyMessage: 'no coverage data available' })
   }
+
+  async handle({ protocol, hostAndPath, buildId }) {
+    // JetBrains Docs: https://confluence.jetbrains.com/display/TCD18/REST+API#RESTAPI-Statistics
+    const buildLocator = `buildType:(id:${buildId})`
+    const apiPath = `app/rest/builds/${encodeURIComponent(
+      buildLocator
+    )}/statistics`
+    const data = await this.fetch({
+      protocol,
+      hostAndPath,
+      apiPath,
+      schema: buildStatisticsSchema,
+    })
+
+    const { coverage } = this.transform({ data })
+    return this.constructor.render({ coverage })
+  }
 }
diff --git a/services/twitter/twitter.service.js b/services/twitter/twitter.service.js
index 499891d1164985077095678fe9840a5d846ef3cd..4344036f319fb80d11ffb17a6fe57c8139c01bc7 100644
--- a/services/twitter/twitter.service.js
+++ b/services/twitter/twitter.service.js
@@ -94,14 +94,6 @@ class TwitterFollow extends BaseJsonService {
     }
   }
 
-  async fetch({ user }) {
-    return this._requestJson({
-      schema,
-      url: `http://cdn.syndication.twimg.com/widgets/followbutton/info.json`,
-      options: { qs: { screen_names: user } },
-    })
-  }
-
   static render({ user, followers }) {
     return {
       label: `follow @${user}`,
@@ -114,6 +106,14 @@ class TwitterFollow extends BaseJsonService {
     }
   }
 
+  async fetch({ user }) {
+    return this._requestJson({
+      schema,
+      url: `http://cdn.syndication.twimg.com/widgets/followbutton/info.json`,
+      options: { qs: { screen_names: user } },
+    })
+  }
+
   async handle({ user }) {
     const data = await this.fetch({ user })
     if (data.length === 0) {
diff --git a/services/uptimerobot/uptimerobot-ratio.service.js b/services/uptimerobot/uptimerobot-ratio.service.js
index 06d4e897a2ef60dc9f783e3c3fbd3b8a33d78137..377a00343a3e9a93b13fb40a31f386b64b81b4bd 100644
--- a/services/uptimerobot/uptimerobot-ratio.service.js
+++ b/services/uptimerobot/uptimerobot-ratio.service.js
@@ -6,12 +6,6 @@ const UptimeRobotBase = require('./uptimerobot-base')
 const ratioColor = colorScale([10, 30, 50, 70])
 
 module.exports = class UptimeRobotRatio extends UptimeRobotBase {
-  static get defaultBadgeData() {
-    return {
-      label: 'uptime',
-    }
-  }
-
   static get route() {
     return {
       base: 'uptimerobot/ratio',
@@ -40,6 +34,12 @@ module.exports = class UptimeRobotRatio extends UptimeRobotBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'uptime',
+    }
+  }
+
   static render({ ratio }) {
     return {
       message: `${ratio}%`,
diff --git a/services/uptimerobot/uptimerobot-status.service.js b/services/uptimerobot/uptimerobot-status.service.js
index 9af5698faccb9046766fc9e1e8c903e0859beedb..92921c8769a6153bf35ef38ff6b6425f24db154c 100644
--- a/services/uptimerobot/uptimerobot-status.service.js
+++ b/services/uptimerobot/uptimerobot-status.service.js
@@ -3,12 +3,6 @@
 const UptimeRobotBase = require('./uptimerobot-base')
 
 module.exports = class UptimeRobotStatus extends UptimeRobotBase {
-  static get defaultBadgeData() {
-    return {
-      label: 'status',
-    }
-  }
-
   static get route() {
     return {
       base: 'uptimerobot/status',
@@ -28,6 +22,12 @@ module.exports = class UptimeRobotStatus extends UptimeRobotBase {
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'status',
+    }
+  }
+
   static render({ status }) {
     switch (status) {
       case 0:
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
index 877c139c078b77c8aecd1986310794a535b469ca..76cdf576d7a99c80ea6c675c24cee74a18e2e35f 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
@@ -26,19 +26,6 @@ module.exports = class VisualStudioMarketplaceAzureDevOpsInstalls extends Visual
     }
   }
 
-  static get defaultBadgeData() {
-    return {
-      label: 'installs',
-    }
-  }
-
-  static render({ count }) {
-    return {
-      message: metric(count),
-      color: downloadCount(count),
-    }
-  }
-
   static get examples() {
     return [
       {
@@ -54,6 +41,19 @@ module.exports = class VisualStudioMarketplaceAzureDevOpsInstalls extends Visual
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'installs',
+    }
+  }
+
+  static render({ count }) {
+    return {
+      message: metric(count),
+      color: downloadCount(count),
+    }
+  }
+
   async handle({ measure, extensionId }) {
     const json = await this.fetch({ extensionId })
     const { statistics } = this.transformStatistics({ json })
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
index 2317d1894abdfd43e1a534a8c47a9859e4c6a7dd..921670c8404fbdf4b138a3669ef90369804d1ca9 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
@@ -26,16 +26,6 @@ module.exports = class VisualStudioMarketplaceDownloads extends VisualStudioMark
     }
   }
 
-  static render({ measure, count }) {
-    const label = measure === 'd' ? 'downloads' : 'installs'
-
-    return {
-      label,
-      message: metric(count),
-      color: downloadCount(count),
-    }
-  }
-
   static get examples() {
     return [
       {
@@ -57,6 +47,16 @@ module.exports = class VisualStudioMarketplaceDownloads extends VisualStudioMark
     ]
   }
 
+  static render({ measure, count }) {
+    const label = measure === 'd' ? 'downloads' : 'installs'
+
+    return {
+      label,
+      message: metric(count),
+      color: downloadCount(count),
+    }
+  }
+
   async handle({ measure, extensionId }) {
     const json = await this.fetch({ extensionId })
     const { statistics } = this.transformStatistics({ json })
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
index fe748619c2bcb5eb2d7e349cc065266eb7373a79..8e457c7a36dc91f52810cdf806b13d36593caa04 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
@@ -17,23 +17,6 @@ module.exports = class VisualStudioMarketplaceRating extends VisualStudioMarketp
     }
   }
 
-  static get defaultBadgeData() {
-    return {
-      label: 'rating',
-    }
-  }
-
-  static render({ format, averageRating, ratingCount }) {
-    const message =
-      format === 'r'
-        ? `${averageRating.toFixed(1)}/5 (${ratingCount})`
-        : starRating(averageRating)
-    return {
-      message,
-      color: floorCount(averageRating, 2, 3, 4),
-    }
-  }
-
   static get examples() {
     return [
       {
@@ -60,6 +43,23 @@ module.exports = class VisualStudioMarketplaceRating extends VisualStudioMarketp
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'rating',
+    }
+  }
+
+  static render({ format, averageRating, ratingCount }) {
+    const message =
+      format === 'r'
+        ? `${averageRating.toFixed(1)}/5 (${ratingCount})`
+        : starRating(averageRating)
+    return {
+      message,
+      color: floorCount(averageRating, 2, 3, 4),
+    }
+  }
+
   async handle({ format, extensionId }) {
     const json = await this.fetch({ extensionId })
     const { statistics } = this.transformStatistics({ json })
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
index 7431fbdcd4da44cd8864db326eb1ec0ad3d1314a..a42fdc52f995b66b6c5c6fa2aa0196dd2ef151c4 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
@@ -15,16 +15,6 @@ module.exports = class VisualStudioMarketplaceVersion extends VisualStudioMarket
     }
   }
 
-  static get defaultBadgeData() {
-    return {
-      label: 'version',
-    }
-  }
-
-  static render({ version }) {
-    return renderVersionBadge({ version })
-  }
-
   static get examples() {
     return [
       {
@@ -37,6 +27,16 @@ module.exports = class VisualStudioMarketplaceVersion extends VisualStudioMarket
     ]
   }
 
+  static get defaultBadgeData() {
+    return {
+      label: 'version',
+    }
+  }
+
+  static render({ version }) {
+    return renderVersionBadge({ version })
+  }
+
   transform({ json }) {
     const { extension } = this.transformExtension({ json })
     const version = extension.versions[0].version
diff --git a/services/waffle/waffle-label.service.js b/services/waffle/waffle-label.service.js
index 095e75fbf3b6cf8dec90c1d24f095dea0f71a477..653ec6ad0cf4f871efe4dc40986e0f0939dc1cb6 100644
--- a/services/waffle/waffle-label.service.js
+++ b/services/waffle/waffle-label.service.js
@@ -23,33 +23,15 @@ module.exports = class WaffleLabel extends BaseJsonService {
     return 'issue-tracking'
   }
 
-  static get route() {
-    return {
-      base: 'waffle/label',
-      pattern: ':user/:repo/:label',
-    }
-  }
-
-  static get defaultBadgeData() {
-    return { label: 'waffle' }
-  }
-
   static get isDeprecated() {
     const now = new Date()
     return now.getTime() >= new Date('2019-05-16')
   }
 
-  static render({ label, color, count }) {
-    if (count === 'absent') {
-      return { message: count }
-    }
-    if (count === 0 || !color) {
-      color = '78bdf2'
-    }
+  static get route() {
     return {
-      label,
-      message: metric(count),
-      color,
+      base: 'waffle/label',
+      pattern: ':user/:repo/:label',
     }
   }
 
@@ -71,6 +53,24 @@ module.exports = class WaffleLabel extends BaseJsonService {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'waffle' }
+  }
+
+  static render({ label, color, count }) {
+    if (count === 'absent') {
+      return { message: count }
+    }
+    if (count === 0 || !color) {
+      color = '78bdf2'
+    }
+    return {
+      label,
+      message: metric(count),
+      color,
+    }
+  }
+
   async fetch({ user, repo }) {
     const url = `https://api.waffle.io/${user}/${repo}/columns`
     return this._requestJson({
diff --git a/services/wercker/wercker.service.js b/services/wercker/wercker.service.js
index 24a32c83f0ba9729165bf6134d821c93b76f5fbf..267887e92c62555d1bdb7bd8bf0f662389a57fd7 100644
--- a/services/wercker/wercker.service.js
+++ b/services/wercker/wercker.service.js
@@ -15,53 +15,6 @@ const werckerSchema = Joi.array()
   .required()
 
 module.exports = class Wercker extends BaseJsonService {
-  static getBaseUrl({ projectId, applicationName }) {
-    if (applicationName) {
-      return `https://app.wercker.com/api/v3/applications/${applicationName}/builds`
-    } else {
-      return `https://app.wercker.com/api/v3/runs?applicationId=${projectId}`
-    }
-  }
-
-  async fetch({ baseUrl, branch }) {
-    return this._requestJson({
-      schema: werckerSchema,
-      url: baseUrl,
-      options: {
-        qs: {
-          branch,
-          limit: 1,
-        },
-      },
-      errorMessages: {
-        401: 'private application not supported',
-        404: 'application not found',
-      },
-    })
-  }
-
-  static render({ result }) {
-    return renderBuildStatusBadge({ status: result })
-  }
-
-  async handle({ projectId, applicationName, branch }) {
-    const json = await this.fetch({
-      baseUrl: this.constructor.getBaseUrl({
-        projectId,
-        applicationName,
-      }),
-      branch,
-    })
-    if (json.length === 0) {
-      return this.constructor.render({
-        result: 'not built',
-      })
-    }
-    const { result } = json[0]
-    return this.constructor.render({ result })
-  }
-
-  // Metadata
   static get category() {
     return 'build'
   }
@@ -113,4 +66,50 @@ module.exports = class Wercker extends BaseJsonService {
       },
     ]
   }
+
+  static render({ result }) {
+    return renderBuildStatusBadge({ status: result })
+  }
+
+  static getBaseUrl({ projectId, applicationName }) {
+    if (applicationName) {
+      return `https://app.wercker.com/api/v3/applications/${applicationName}/builds`
+    } else {
+      return `https://app.wercker.com/api/v3/runs?applicationId=${projectId}`
+    }
+  }
+
+  async fetch({ baseUrl, branch }) {
+    return this._requestJson({
+      schema: werckerSchema,
+      url: baseUrl,
+      options: {
+        qs: {
+          branch,
+          limit: 1,
+        },
+      },
+      errorMessages: {
+        401: 'private application not supported',
+        404: 'application not found',
+      },
+    })
+  }
+
+  async handle({ projectId, applicationName, branch }) {
+    const json = await this.fetch({
+      baseUrl: this.constructor.getBaseUrl({
+        projectId,
+        applicationName,
+      }),
+      branch,
+    })
+    if (json.length === 0) {
+      return this.constructor.render({
+        result: 'not built',
+      })
+    }
+    const { result } = json[0]
+    return this.constructor.render({ result })
+  }
 }
diff --git a/services/wheelmap/wheelmap.service.js b/services/wheelmap/wheelmap.service.js
index f463c893553e93e9580262f43468bfdd5ef5e030..f6861b3ad9365717bc2f680451ee32da6056ee23 100644
--- a/services/wheelmap/wheelmap.service.js
+++ b/services/wheelmap/wheelmap.service.js
@@ -11,6 +11,43 @@ const wheelmapSchema = Joi.object({
 }).required()
 
 module.exports = class Wheelmap extends BaseJsonService {
+  static get category() {
+    return 'other'
+  }
+
+  static get route() {
+    return {
+      base: 'wheelmap/a',
+      pattern: ':nodeId(-?[0-9]+)',
+    }
+  }
+
+  static get examples() {
+    return [
+      {
+        title: 'Wheelmap',
+        namedParams: { nodeId: '26699541' },
+        staticPreview: this.render({ accessibility: 'yes' }),
+      },
+    ]
+  }
+
+  static get defaultBadgeData() {
+    return { label: 'accessibility' }
+  }
+
+  static render({ accessibility }) {
+    let color
+    if (accessibility === 'yes') {
+      color = 'brightgreen'
+    } else if (accessibility === 'limited') {
+      color = 'yellow'
+    } else if (accessibility === 'no') {
+      color = 'red'
+    }
+    return { message: accessibility, color }
+  }
+
   async fetch({ nodeId }) {
     let options
     if (serverSecrets.wheelmap_token) {
@@ -32,46 +69,9 @@ module.exports = class Wheelmap extends BaseJsonService {
     })
   }
 
-  static render({ accessibility }) {
-    let color
-    if (accessibility === 'yes') {
-      color = 'brightgreen'
-    } else if (accessibility === 'limited') {
-      color = 'yellow'
-    } else if (accessibility === 'no') {
-      color = 'red'
-    }
-    return { message: accessibility, color }
-  }
-
   async handle({ nodeId }) {
     const json = await this.fetch({ nodeId })
     const accessibility = json.node.wheelchair
     return this.constructor.render({ accessibility })
   }
-
-  static get defaultBadgeData() {
-    return { label: 'accessibility' }
-  }
-
-  static get category() {
-    return 'other'
-  }
-
-  static get route() {
-    return {
-      base: 'wheelmap/a',
-      pattern: ':nodeId(-?[0-9]+)',
-    }
-  }
-
-  static get examples() {
-    return [
-      {
-        title: 'Wheelmap',
-        namedParams: { nodeId: '26699541' },
-        staticPreview: this.render({ accessibility: 'yes' }),
-      },
-    ]
-  }
 }
diff --git a/services/wordpress/wordpress-downloads.service.js b/services/wordpress/wordpress-downloads.service.js
index 48655b735887ba960c08a3af598993e9bf6e6329..5a5aeeb830209dcb67b46cec51887773fefdecfd 100644
--- a/services/wordpress/wordpress-downloads.service.js
+++ b/services/wordpress/wordpress-downloads.service.js
@@ -29,29 +29,10 @@ function DownloadsForExtensionType(extensionType) {
       return `Wordpress${capt}Downloads`
     }
 
-    static render({ downloads }) {
-      return {
-        message: metric(downloads),
-        color: downloadCount(downloads),
-      }
-    }
-
-    async handle({ slug }) {
-      const { downloaded: downloads } = await this.fetch({
-        extensionType,
-        slug,
-      })
-      return this.constructor.render({ downloads })
-    }
-
     static get category() {
       return 'downloads'
     }
 
-    static get defaultBadgeData() {
-      return { label: 'downloads' }
-    }
-
     static get route() {
       return {
         base: `wordpress/${extensionType}/dt`,
@@ -68,38 +49,38 @@ function DownloadsForExtensionType(extensionType) {
         },
       ]
     }
-  }
-}
-
-function InstallsForExtensionType(extensionType) {
-  const { capt, exampleSlug } = extensionData[extensionType]
-
-  return class WordpressInstalls extends BaseWordpress {
-    static get name() {
-      return `Wordpress${capt}Installs`
-    }
 
-    static get category() {
-      return 'downloads'
+    static get defaultBadgeData() {
+      return { label: 'downloads' }
     }
 
-    static render({ installCount }) {
+    static render({ downloads }) {
       return {
-        message: metric(installCount),
-        color: downloadCount(installCount),
+        message: metric(downloads),
+        color: downloadCount(downloads),
       }
     }
 
     async handle({ slug }) {
-      const { active_installs: installCount } = await this.fetch({
+      const { downloaded: downloads } = await this.fetch({
         extensionType,
         slug,
       })
-      return this.constructor.render({ installCount })
+      return this.constructor.render({ downloads })
     }
+  }
+}
 
-    static get defaultBadgeData() {
-      return { label: 'active installs' }
+function InstallsForExtensionType(extensionType) {
+  const { capt, exampleSlug } = extensionData[extensionType]
+
+  return class WordpressInstalls extends BaseWordpress {
+    static get name() {
+      return `Wordpress${capt}Installs`
+    }
+
+    static get category() {
+      return 'downloads'
     }
 
     static get route() {
@@ -118,6 +99,25 @@ function InstallsForExtensionType(extensionType) {
         },
       ]
     }
+
+    static get defaultBadgeData() {
+      return { label: 'active installs' }
+    }
+
+    static render({ installCount }) {
+      return {
+        message: metric(installCount),
+        color: downloadCount(installCount),
+      }
+    }
+
+    async handle({ slug }) {
+      const { active_installs: installCount } = await this.fetch({
+        extensionType,
+        slug,
+      })
+      return this.constructor.render({ installCount })
+    }
   }
 }
 
@@ -158,10 +158,6 @@ function DownloadsForInterval(interval) {
       return 'downloads'
     }
 
-    static get defaultBadgeData() {
-      return { label: 'downloads' }
-    }
-
     static get route() {
       return {
         base,
@@ -179,6 +175,10 @@ function DownloadsForInterval(interval) {
       ]
     }
 
+    static get defaultBadgeData() {
+      return { label: 'downloads' }
+    }
+
     static render({ downloads }) {
       return {
         message: `${metric(downloads)}${messageSuffix}`,
diff --git a/services/wordpress/wordpress-platform.service.js b/services/wordpress/wordpress-platform.service.js
index 66cc59ba6680c9ba53af11c2fe065cc9642073b1..c7f16d2b3bc0ef8644f1f36dbf27ff6e4287ed77 100644
--- a/services/wordpress/wordpress-platform.service.js
+++ b/services/wordpress/wordpress-platform.service.js
@@ -52,10 +52,6 @@ class WordpressPluginTestedVersion extends BaseWordpress {
     return 'platform-support'
   }
 
-  static get defaultBadgeData() {
-    return { label: 'wordpress' }
-  }
-
   static get route() {
     return {
       base: `wordpress/plugin/tested`,
@@ -75,6 +71,10 @@ class WordpressPluginTestedVersion extends BaseWordpress {
     ]
   }
 
+  static get defaultBadgeData() {
+    return { label: 'wordpress' }
+  }
+
   static renderStaticPreview({ testedVersion }) {
     // Since this badge has an async `render()` function, but `get examples()` has to
     // be synchronous, this method exists. It should return the same value as the