question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Intent to implement: AMP Access client-side via iframe

See original GitHub issue

Introduction

AMP Access spec provides a way for to lock/unlock content.

At the core of the protocol are three concepts:

  1. AMP Reader ID. Globally unique session identifier in AMP context.
  2. Authorization endpoint. A credentialed CORS GET HTTPS endpoint that returns the authorization response that can be used to unlock premium content. It can also be used to render auxiliary sections, such as growls.
  3. Pingback endpoint. A credentialed CORS POST HTTPS endpoint that confirms the impression.

Metering implementation is specifically described in the Metering section of the AMP Access spec. It suggests that publishers store metering count on their backend system keyed by AMP Reader ID and/or any session information delivered via CORS protocol.

The goal of this ITI is to create a client-side solution that does not require CORS request (or doesn’t always require it). This solution is based on 3p iframes.

Some important considerations when designing this solution:

  1. Performance. Putting an iframe loading into critical path of document rendering is CPU/memory-heavy and slow. A typical iframe is has a multi-stage loading/execution sequence: load and parse iframe HTML, load main JavaScript, which in turn likely executes a remote XHR. So, this could be as bad as three sequential network requests before the response can be returned. All of these combined could easily reach into > 7s average. Some steps here optimizable, such as JavaScript can be directly bundled into HTML. But it’s hard to require such an optimization.
  2. Local storage and cookie spaces could be partitioned on some browsers and Safari ITP makes this even less predictable.

The solution

The solution has several components:

  1. Iframe config and instantiation, parametrized by the AMP Access configuration.
  2. Iframe communication protocol to invoke authorize and pingback methods.
  3. AMP-side caching solution with strict one-behind semantics.
  4. AMP-side timeout semantics with one-behind continuation.

Iframe config and instantiation

This part is very straightforward. It roughly executed as following.

First, the new config extension is provided:

<script id="amp-access" type="application/json">
{
  "type": "iframe",
  "iframeSrc": "https://pub/iframe",
  "iframeVars": [
    "EXPRESSION1",
    "EXPRESSION2",
    ...
  ],
  "defaultResponse": {
    ...
  },
  // Additional properties.
}
</script>

The iframe is instantiated as following:

const iframeController = createIframe(config.src);
iframeController.connect(config).then(() => {
  // Continue to authorization, etc.
});

Iframe communication protocol

AMP will define communication protocol to invoke iframe’s methods, most notably authorize and pingback.

Most important, the iframe will establish connection with AMP Runtime via a basic handshake:

  1. When iframe is ready, it will exchange handshake messages with the AMP Runtime which will include config object.
  2. The iframe will first confirm the origin of the AMP page and then perform its internal init/config steps. The iframe then will accept the connection.
  3. After this, the AMP page and the iframe can communicate freely.

To execute authorization, AMP Runtime will:

  1. Resolve all variables requested in the config.iframeVars.
  2. Send authorize message to the iframe that includes these variables.
  3. Await the authorize-response response message.
  4. Apply authorization response as it does now.

To execute pingback, AMP Runtime will:

  1. Resolve all variables requested in the config.pingbackVars.
  2. Send pingback message to the iframe that includes these variables.

AMP-side caching with one-behind semantics

So far, this proposal is simple and similar to the AMP Access spec with CORS. However, this section will attempt to address performance issues. We’d like to use the previous response for the next page impression if possible. For the first visit, we also get some of the worst performance factors. So, we would rely on the defaultResponse to do the initial rendering when cache is not available, which will be assumed to be positive. However, we can speed up the follow up impression. The steps are:

  1. If the authorization response is available in the local storage of the AMP Runtime and it’s a positive response, use it to open up the page immediately. Delay rendering of any templates, however.
  2. If the authorization response is not available in the local storage, open the page immediately using the defaultResponse.
  3. In either case, in parallel, run the authorization iframe request. Include the previous response as an argument (this could also help with some storage inconsistencies).
  4. Wait for the new response.
  5. Store new response in the local storage of the AMP Runtime.
  6. Render templates, if any, using the new response.

This requires us to define the notion of the positive response. It means that the authorization response grants read access. We will start by mandating a boolean granted field in the authorization response.

The cache can have an upper-bound expiration limit, e.g. the cached response is dropped after 7 days.

Thus, only the negative authorizations are render-blocking. Depending on metering quota, this could significantly reduce optimistic render blocks. It’d also normally result in no more than one extra view by the user.

AMP-side timeout semantics and one-behind

In case of previous negative response, the authorization is render-blocking. We normally apply a strict time-out of 3 seconds to authorization requests and we’d like to do the same here.

However, we can do one improvement: even if we timeout the authorization, we can still allow the iframe authorization request to continue and update the cache ones it completes. Thus, the next impression should hopefully proceed faster.


Based on #2970.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:13 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
dvoytenkocommented, Mar 27, 2018

@czarnechmurki amp-iframe-api-export.js is just the concatenation of two files: messenger.js and iframe-api.js. The synchronous /dist.3p/current/amp-iframe-api-export.js is just an example. Concatenation can be done manually, using tools such as rollup, or just take amp-iframe-api-export.js file we provide and drop it in your project. You most likely will want to compile these two files into your own JS binary to avoid extra downloads and sync issues - the startup time for this iframe is pretty important so reducing number of binaries would help.

We will eventually deploy bundled messenger.js and iframe-api.js as an npm module for those who manage dependencies/compile via npm. Let us know if it’d help you.

1reaction
dvoytenkocommented, Mar 27, 2018

The #14254 adds configuration parameters, defines authorization response more clearly and adds more docs.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Include iframes - amp.dev
Learn how to display include media content in your pages, and how to use iframes to display advanced content outside of AMP's limitations....
Read more >
Proposal for promotable IFRAME - WICG
In AMP's case, this works by: Loading a number of search result target pages in hidden iframes while the search results are displayed;...
Read more >
Server-side Tagging In Google Tag Manager - Simo Ahava
An introduction to Server-side tagging in Google Tag Manager. The article contains examples and walkthroughs for getting started with the ...
Read more >
From object to iframe — other embedding technologies
A long time ago on the Web, it was popular to use frames to create websites — small parts of a website stored...
Read more >
4.8.2 The iframe element — HTML5 - W3C
For iframe elements in HTML documents, the attribute, if present, must have a value using the HTML ... <p>you should get earl&amp;me on...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found