diff --git a/bin/configure-fastly.js b/bin/configure-fastly.js
index 595fcd9b2..fc133a7d2 100644
--- a/bin/configure-fastly.js
+++ b/bin/configure-fastly.js
@@ -77,12 +77,17 @@ var getAppRouteCondition = function (pathToStatic, routes, additionalPaths) {
     return pathsToCondition(allPaths);
 };
 
-var getConditionNameForView = function (view) {
-    return 'routes/' + view;
+var getConditionNameForRoute = function (route, type) {
+    return 'routes/' + route.pattern + ' (' + type + ')';
 };
 
-var getHeaderNameForView = function (view) {
-    return 'rewrites/' + view;
+var getHeaderNameForRoute = function (route) {
+    if (route.view) return 'rewrites/' + route.view;
+    if (route.redirect) return 'redirects/' + route.pattern;
+};
+
+var getResponseNameForRoute = function (route) {
+    return 'redirects/' + route.pattern;
 };
 
 async.auto({
@@ -167,7 +172,7 @@ async.auto({
         var conditions = {};
         async.forEachOf(routes, function (route, id, cb2) {
             var condition = {
-                name: getConditionNameForView(route.view),
+                name: getConditionNameForRoute(route, 'request'),
                 statement: 'req.url ~ "' + route.pattern + '"',
                 type: 'REQUEST',
                 priority: id
@@ -185,21 +190,60 @@ async.auto({
     appRouteHeaders: ['version', 'appRouteRequestConditions', function (cb, results) {
         var headers = {};
         async.forEachOf(routes, function (route, id, cb2) {
-            var header = {
-                name: getHeaderNameForView(route.view),
-                action: 'set',
-                ignore_if_set: 0,
-                type: 'request',
-                dst: 'url',
-                src: '"/' + route.view + '.html"',
-                request_condition: results.appRouteRequestConditions[id].name,
-                priority: 10
-            };
-            fastly.setFastlyHeader(results.version, header, function (err, response) {
-                if (err) return cb2(err);
-                headers[id] = response;
-                cb2(null, response);
-            });
+            if (route.redirect) {
+                async.auto({
+                    responseCondition: function (cb3) {
+                        var condition = {
+                            name: getConditionNameForRoute(route, 'response'),
+                            statement: 'req.url ~ "' + route.pattern + '"',
+                            type: 'RESPONSE',
+                            priority: id
+                        };
+                        fastly.setCondition(results.version, condition, cb3);
+                    },
+                    responseObject: function (cb3) {
+                        var responseObject = {
+                            name: getResponseNameForRoute(route),
+                            status: 301,
+                            response: 'Moved Permanently',
+                            request_condition: getConditionNameForRoute(route, 'request')
+                        };
+                        fastly.setResponseObject(results.version, responseObject, cb3);
+                    },
+                    redirectHeader: ['responseCondition', function (cb3, redirectResults) {
+                        var header = {
+                            name: getHeaderNameForRoute(route),
+                            action: 'set',
+                            ignore_if_set: 0,
+                            type: 'RESPONSE',
+                            dst: 'http.Location',
+                            src: '"' + route.redirect + '"',
+                            response_condition: redirectResults.responseCondition.name
+                        };
+                        fastly.setFastlyHeader(results.version, header, cb3);
+                    }]
+                }, function (err, redirectResults) {
+                    if (err) return cb2(err);
+                    headers[id] = redirectResults.redirectHeader;
+                    cb2(null, redirectResults);
+                });
+            } else {
+                var header = {
+                    name: getHeaderNameForRoute(route, 'request'),
+                    action: 'set',
+                    ignore_if_set: 0,
+                    type: 'REQUEST',
+                    dst: 'url',
+                    src: '"/' + route.view + '.html"',
+                    request_condition: results.appRouteRequestConditions[id].name,
+                    priority: 10
+                };
+                fastly.setFastlyHeader(results.version, header, function (err, response) {
+                    if (err) return cb2(err);
+                    headers[id] = response;
+                    cb2(null, response);
+                });
+            }
         }, function (err) {
             if (err) return cb(err);
             cb(null, headers);
diff --git a/bin/lib/fastly-extended.js b/bin/lib/fastly-extended.js
index a41da1a4c..f54f231ae 100644
--- a/bin/lib/fastly-extended.js
+++ b/bin/lib/fastly-extended.js
@@ -110,6 +110,38 @@ module.exports = function (apiKey, serviceId) {
         }.bind(this));
     };
 
+    /*
+     * setResponseObject: Upsert a Fastly response object
+     * Attempts to PUT and POSTs if the PUT request is a 404
+     *
+     * @param {number} Version number
+     * @param {object} Response object sent to the API
+     * @param {callback} Callback for fastly.request
+     */
+    fastly.setResponseObject = function (version, responseObj, cb) {
+        if (!this.serviceId) {
+            cb('Failed to set response object. No serviceId configured');
+        }
+        var name = responseObj.name;
+        var putUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object/' + encodeURIComponent(name);
+        var postUrl = this.getFastlyAPIPrefix(this.serviceId, version) + '/response_object';
+        return this.request('PUT', putUrl, responseObj, function (err, response) {
+            if (err && err.statusCode === 404) {
+                this.request('POST', postUrl, responseObj, function (err, response) {
+                    if (err) {
+                        return cb('Failed to insert response object: ' + err);
+                    }
+                    return cb(null, response);
+                });
+                return;
+            }
+            if (err) {
+                return cb('Failed to update response object: ' + err);
+            }
+            return cb(null, response);
+        }.bind(this));
+    };
+
     /*
      * cloneVersion: Clone a version to create a new version
      *
diff --git a/src/routes.json b/src/routes.json
index 371d67fcf..583d69183 100644
--- a/src/routes.json
+++ b/src/routes.json
@@ -45,7 +45,7 @@
         "title": "LEGO WeDo 2.0"
     },
     {
-        "pattern": "/info/donate/",
+        "pattern": "^/info/donate",
         "redirect": "https://secure.donationpay.org/scratchfoundation/"
     }
 ]