Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add element viewability triggers for amp-analytics #1297

Closed
rudygalfi opened this issue Jan 5, 2016 · 21 comments
Closed

Add element viewability triggers for amp-analytics #1297

rudygalfi opened this issue Jan 5, 2016 · 21 comments
Assignees
Labels
INTENT TO IMPLEMENT Proposes implementation of a significant new feature. https://bit.ly/amp-contribute-code Type: Feature Request WG: analytics

Comments

@rudygalfi
Copy link
Contributor

Offshoot from #871.

We currently support a document viewability triggers in amp-analytics. This request is to support triggers at the element level.

cc @avimehta @btownsend

@rudygalfi
Copy link
Contributor Author

cc @cramforce who mentioned implementing this by dispatching DOM events on AMP elements when they become visible and stop being visible.

@rudygalfi rudygalfi added this to the M? milestone Jan 22, 2016
@avimehta avimehta self-assigned this Mar 16, 2016
@avimehta
Copy link
Contributor

avimehta commented Mar 16, 2016

The main goal of this issue is to enable element level measurement of viewability. For best performance and to keep user experience good, the APIs mentioned below only work for amp-* elements. We already do a lot of the required calculations for these elements and additional work should not affect the performance severely.

The API/configuration comes into play when the trigger is set to fire on visible. Since there is no existing configuration that applies to triggers of type visible, the new configuration should be backward-compatible.

The API allows for additional conditions, all of which have to be true, that determine whether the trigger should be fired or not.

API configuration:

Visible Percentage

These conditions keep track of the amount of element visible in vieweport at any given time. They get triggered when the percentage of element visible is between min and max (if specified). The properties that enable these conditions are named visiblePercentageMin and visiblePercentageMax. Valid values are 0-100 (both included).

Continuous Time

These conditions keep track of the amount of time (any part of) an element has been in the viewport and fire when the time is between the minimum and maximum configured time. These conditions are configured using continuousTimeMin and continuousTimeMax. The time is expressed in milliseconds.

Total Time

These conditions keep track of total time for which any part of an element is on screen and fire when the time is between minimum and maximum. These conditions are configured using totalTimeMin and totalTimeMax. The time is expressed in milliseconds.

Unload

As the name suggests, this condition is true only when the page is in the process of being unloaded. Since using onbeforeunload and onunload are considered to be harmful for caching, this condition is provided only on a best effort basis. (details on how this will be implemented are TBD. pagehide is promising; look into it.)

Additional implementation details:

  • All the min values should be less than the max values. If not, both the conditions will be ignored.
  • When any of the conditions mentioned above are not specified, certain defaults are used. For time based and percentage conditions, no maximum value results in the condition to be not evaluated.
  • The trigger fires only once per page. It is fired as soon as all the conditions are met.

Summary

  "visibilitySpec": {
    "selector": <element id>,
    "visiblePercentageMin": <%>,
    "visiblePercentageMax": <%>,
    "continuousTimeMin": <milliseconds>,
    "continuousTimeMax": <milliseconds>,
    "totalTimeMin": <milliseconds>,
    "totalTimeMax": <milliseconds>,
    "unload": true
  }

Examples

visiblePercentageMin: 50
continuousTimeMin: 1000

This should fire as soon as at least 50% of the ad has been on the screen continuously for 1 second.

visiblePercentageMin: 1
totalTimeMin: 1000

This will fire after at least 1% of the ad has been on the screen for a total of 1 second.

unload: true
visiblePercentageMin: 50
continuousTimeMin: 1
continuousTimeMax: 999

This will fire when an ad is at least 50% on screen for at least 1ms, but it is unloaded before it can get to 1s.

Complete tagging example

<amp-analytics>
<script type="application-json">
{
  "requests": {
    "format1": "https://myanalytics.com/id=${id}&ct=${continousTime}&vpn=${visiblePercent}",
    "format2": "https://myanalytics.com/id=${id}&unload=1&ct=${totalTime}&vpx=${vpx}"
  },
  "vars": {
    "id": "123456"
  },
  "triggers": {
    "continuousVisible": {
      "on": "visible",
      "request": "format1",
      "visibilitySpec": {
        "selector": "adsElementSelector",
        "visiblePercentageMin": 50,
        "visiblePercentageMax": 74,
        "continuousTimeMin": 1000,
        "continuousTimeMax": 2000
      }
    },
    "unload": {
      "on": "visible",
      "request": "format2"
      "visibilitySpec": {
        "selector": "adsElementSelector",
        "unload": true
      }
    }
  }
}
</script>
</amp-analytics>

Additional variables to be supported

Descriptions of the following are still pending. Names should give an indication of what they are about.

minVisiblePercentage
The minimum visible percentage over the time that this criteria was met. For example, a ping where the element was 100%, then off the page, then 100% will report this value as 0. A ping with visiblePercentageMin=50 condition undergoing the same transitions would report somewhere between 50 and 100.

maxVisiblePercentage
Same as above, except it keeps track of the max. The maximum visible percentage over the time that this criteria was met. For example, a ping where the element was 100%, then off the page, then 100% will report this value as 100. A ping with visiblePercentageMax=50 undergoing the same transitions would report somewhere between 0 and 50 since any time where the element was 100% on the page would not be counted.

totalVisibleTime
The total time that the element has met the visiblity conditions at time this ping is sent.

continuousVisibleTime
The maximum amount of continuous time this ad has met the visible criteria at the time this ping is sent. Note that a ping with a continuous-time-min=1000 and total-time-min=5000 that is visible for 1000ms, then not visible, then visible for 2000ms, then not, then visible for 1000ms, then not, then visible for 1020ms will report 2000 for this number as that is the max continuous visible time, even if it is not the current continuous visible time (1020 in this example).

firstSeenTime
Time that at least 1px of the element is on the screen for the first time since javascript load.

lastSeenTime
Time that at least 1px of the element is on the screen for the last time since javascript load.

firstVisibleTime
Time that the element met visibility conditions for the first time since javascript load.

lastVisibleTime
Time that the element met visibility conditions for the last time since javascript load.

Still pending:

  • AMP_SELECTOR_X
  • AMP_SELECTOR_Y
  • AMP_HOVER_TIME
  • AMP_TOTAL_TIME
  • AMP_ZOOM
  • AMP_LOAD_TIME_VISIBILITY
  • AMP_BACKGROUNDED_AT_START
  • AMP_BACKGROUNDED

/cc @cramforce @btownsend

@dvoytenko
Copy link
Contributor

@avimehta this all sounds good. My only concern if this statement is sufficient:

APIs mentioned below only work for amp-* elements

It's obviously correct that amp- elements would give the best performance, but I'd like to make sure that it solves the problems it needs to solve.

@avimehta
Copy link
Contributor

Currently, This is needed for amp-ads and people might want to implement it for videos, carousel and possible other social widgets. Not sure if text content needs to be tracked at this granular level. Maybe scroll-tracking solves that part?

@dvoytenko
Copy link
Contributor

No, now I get it. Surely then amp- elements is a good first step, at the very least.

@avimehta avimehta added the INTENT TO IMPLEMENT Proposes implementation of a significant new feature. https://bit.ly/amp-contribute-code label Mar 17, 2016
@rudygalfi rudygalfi modified the milestones: Sprint: 2016-04-14 [next], Backlog Mar 24, 2016
@rudygalfi
Copy link
Contributor Author

👍 This would definitely be awesome to add.

Regarding only supporting amp- elements, I agree that we can cover a lot of ground that way, but certainly there are other use cases? For instance, maybe you use a <div> combined with dynamic CSS classes to show some special custom element like a promo. You might want to track viewability of such a thing using this feature. What would be the challenges to tracking, say, any div?

@cramforce
Copy link
Member

From reviewing the PR:

Maybe it is just me, but I find the usage of the Max prefix very confusing. Its really something like TriggerBoundary, right? (Which is obviously a terrible name). The Max to me say: If the user spends more time this doesn't trigger.

@avimehta
Copy link
Contributor

avimehta commented Apr 5, 2016

@cramforce I read it as a set of conditions and the trigger fires when the values are between min and max. One thing to note is that it is possible for the trigger to have a min value but no max value.

@surfcasper any other suggestions for the names?

@cramforce
Copy link
Member

@avimehta So if max is surpassed it doesn't fire? Or does it fire when max is reach or on unload?

@avimehta
Copy link
Contributor

avimehta commented Apr 5, 2016

Lets take the example of

"visibilitySpec": {
  "selector": "elementSelector",
  "visiblePercentageMin": 50,
  "visiblePercentageMax": 74,
  "continuousTimeMin": 1000,
}

As soon as the element has spent 1 continuous second with between 50 and 74 percent (inclusive) of its pixels on the screen, this will fire.

  • Note that if the element is 100% on screen and stays that way, this will never fire.
  • If the element is 100% visible, goes to 60% visibility and then stays that way for 1 second, the trigger will fire.

Lets change the example to following:

"visibilitySpec": {
  "selector": "elementSelector",
  "visiblePercentageMin": 50,
  "visiblePercentageMax": 74,
  "continuousTimeMin": 1000,
  "continuousTimeMax": 2000,
  "unload": true
}

This trigger will fire when all of the following conditions are met:

  • When page is unloading AND
  • The continuous time for which the element was visible between 50% and 74% (inclusive) is between 1 and 2 seconds.
    Notes:
  • The tag does not fire if the continuous time surpasses 2 seconds(or is less than 1 second) by the time unload happens.

@rudygalfi
Copy link
Contributor Author

@avimehta #1608 (comment) inspired me to ask if you will be able to track viewability on non-(amp-*) sub-elements of amp- elements. For example:

<amp-carousel>
  <div>...</div>
</amp-carousel>

Can you track the div in the example above?

@avimehta
Copy link
Contributor

I think it will be trivial to do that but I am not going to do it in the beginning. The calculations we are doing are costly enough that doing it for a subset of elements might affect performance. If we allow all elements to be tracked like this, we will be opening the floodgates. (also, doing these calculations for non-amp elements is costlier than for amp elements.)

avimehta added a commit to avimehta/amphtml that referenced this issue Apr 27, 2016
This allows specification of vars like `veritcalScrollBoundary` etc.
These vars only make sense when particular types of triggers fire and
the valuer is based on the trigger config.

Fixes ampproject#2031. Also helps ampproject#1297
avimehta added a commit that referenced this issue Apr 27, 2016
This allows specification of vars like `veritcalScrollBoundary` etc.
These vars only make sense when particular types of triggers fire and
the valuer is based on the trigger config.

Fixes #2031. Also helps #1297
@ericlindley-g
Copy link
Contributor

Rolling into the next milestone

@j-e-shaw
Copy link

Would it be possible to add AMP_SELECTOR_RIGHT/BOTTOM to go with AMP_SELECTOR_X/Y so we can get the full box?

If not, what about AMP_SELECTOR_WIDTH/HEIGHT?

@avimehta
Copy link
Contributor

Either of those work but I find Width/height a bit more readable. I'll go with that if you don't mind.

@j-e-shaw
Copy link

width/height will work fine. Thanks!

@rudygalfi
Copy link
Contributor Author

@avimehta Can you confirm that #3512 will close this out?

@avimehta
Copy link
Contributor

Lets close this out. the unload trigger is left but I would like to do it a little thoughtfully so that this, #2487 and #2564 all get addressed at the same time.

@rudygalfi
Copy link
Contributor Author

Does unload trigger need its own issue?

@rudygalfi
Copy link
Contributor Author

Or perhaps #2487 covers it?

@rudygalfi
Copy link
Contributor Author

FYI: I opened #4449 to track visibilitySpec supporting non-amp-* elems, which was originally brought up in #1297 (comment).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
INTENT TO IMPLEMENT Proposes implementation of a significant new feature. https://bit.ly/amp-contribute-code Type: Feature Request WG: analytics
Projects
None yet
Development

No branches or pull requests

6 participants