diff --git a/api/.gitignore b/api/.gitignore
deleted file mode 100644
index 85825a526..000000000
--- a/api/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-conf.json
diff --git a/api/app.yaml b/api/app.yaml
index 549dc5615..7b009c73a 100755
--- a/api/app.yaml
+++ b/api/app.yaml
@@ -22,6 +22,9 @@ handlers:
- url: /img
static_dir: img
secure: always
+- url: /scripts
+ static_dir: scripts
+ secure: always
- url: /third_party
static_dir: third_party
secure: always
diff --git a/api/iframe/amp-url-converter.html b/api/iframe/amp-url-converter.html
new file mode 100644
index 000000000..14a47f99d
--- /dev/null
+++ b/api/iframe/amp-url-converter.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/api/scripts/amp_url_converter.js b/api/scripts/amp_url_converter.js
new file mode 100644
index 000000000..7be45d52f
--- /dev/null
+++ b/api/scripts/amp_url_converter.js
@@ -0,0 +1,85 @@
+/**
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS-IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const DEFAULT_URL = "https://www.example.com/amp?param=value";
+const AMP_CACHE_PREFIX = "https://cdn.ampproject.org/c/";
+
+class AmpUrlConverter {
+
+ constructor(root, ampUrlFactory) {
+ this.inputView = root.getElementById('input');
+ this.resultView = root.getElementById('result');
+ this.ampUrlFactory = ampUrlFactory;
+ root.getElementById('execute')
+ .addEventListener("click", this.onClick.bind(this));
+ }
+
+ setInput(urlString) {
+ this.inputView.value = urlString;
+ this.convert(urlString);
+ }
+
+ convert(urlString) {
+ urlString = urlString.trim();
+ if (!urlString) {
+ this.showError('Empty input');
+ return;
+ }
+ try {
+ const ampUrl = this.ampUrlFactory.createAmpUrl(urlString);
+ const proxyUrl = ampUrl.getProxyUrl();
+ this.showResult('' + proxyUrl + '');
+ }catch(e) {
+ this.showError('Invalid URL');
+ }
+ }
+
+ showError(message) {
+ this.resultView.className = 'error';
+ this.resultView.innerHTML = message;
+ }
+
+ showResult(result) {
+ this.resultView.className = '';
+ this.resultView.innerHTML = result;
+ }
+
+ onClick() {
+ this.convert(this.inputView.value);
+ }
+
+}
+
+function getParameterByName(name, defaultValue) {
+ const url = window.location.href;
+ name = name.replace(/[\[\]]/g, "\\$&");
+ const regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
+ results = regex.exec(url);
+ if (!results) { return defaultValue; }
+ if (!results[2]) { return defaultValue; }
+ return decodeURIComponent(results[2].replace(/\+/g, " "));
+}
+
+const proxyUrlPrefix = 'https://cdn.ampproject.org';
+const javascriptVersion = '5';
+const useCurlsEncoding = true;
+const ampUrlFactory =
+ new AmpUrlFactory(proxyUrlPrefix, javascriptVersion, useCurlsEncoding);
+
+const converter = new AmpUrlConverter(document, ampUrlFactory);
+const initialUrl = getParameterByName('url', 'https://www.example.com/amp?param=1');
+
+converter.setInput(initialUrl);
diff --git a/src/30_Advanced/Using_the_Google_AMP_Cache.html b/src/30_Advanced/Using_the_Google_AMP_Cache.html
index f4fbdae9b..f3e512ccb 100644
--- a/src/30_Advanced/Using_the_Google_AMP_Cache.html
+++ b/src/30_Advanced/Using_the_Google_AMP_Cache.html
@@ -5,7 +5,11 @@
@@ -13,23 +17,55 @@
+
+