Skip to content

Commit

Permalink
✨📈 Add analytics trigger for elements that show a tooltip (ampproject…
Browse files Browse the repository at this point in the history
…#25547)

* support for focused and click thru states

* support affiliate links

* types

* stop propagation on click events within affiliate links and embedded components

* add stop propagation in tooltip click

* renaming
  • Loading branch information
Enriqe authored and Micajuine Ho committed Dec 27, 2019
1 parent f422e06 commit 3c4bd04
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 19 deletions.
44 changes: 41 additions & 3 deletions examples/amp-story/analytics.html
Expand Up @@ -43,7 +43,7 @@
"endpoint": "https://raw.githubusercontent.com/ampproject/amphtml/master/examples/img/ampicon.png",
"base": "${endpoint}?${type|default:foo}&path=${canonicalPath}",
"pageView": "${base}?&index=${storyPageIndex}&count=${storyPageCount}&id=${storyPageId}&muted=${storyIsMuted}&progress=${storyProgress}",
"click": "${base}?index=${storyPageIndex}&id=${storyPageId}&bookendTargetHref=${storyBookendTargetHref}&bookendCardType=${storyBookendComponentType}&bookendCardPosition=${storyBookendComponentPosition}"
"click": "${base}?&index=${storyPageIndex}&id=${storyPageId}&bookendTargetHref=${storyBookendTargetHref}&bookendCardType=${storyBookendComponentType}&bookendCardPosition=${storyBookendComponentPosition}"
},
"triggers": {
"trackAnchorClicks": {
Expand All @@ -61,6 +61,16 @@
"eventId": "clickOnBookend"
}
},
"trackFocusedState": {
"on": "story-focus",
"tagName": "a",
"request": "click"
},
"trackClickThru": {
"on": "story-click-through",
"tagName": "a",
"request": "click"
},
"trackPageview": {
"on": "story-page-visible",
"request": "pageView",
Expand Down Expand Up @@ -104,15 +114,43 @@ <h1>Page Two</h1>
<amp-story-page id="p3">
<amp-story-grid-layer template="vertical">
<h1>Page Three</h1>
<a href="google.com">click me</a>
</amp-story-grid-layer>
<amp-story-cta-layer>
<a>click me</a>
</amp-story-grid-layer>
</amp-story-page>

<amp-story-page id="p4">
<amp-story-page id="p4" style="background-color: grey">
<amp-story-grid-layer template="vertical">
<h1>Page Four</h1>
<a id="blink-3" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="shopping-cart">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-4" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="offer">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-5" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="flight">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-6" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="hotel">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-7" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="movie">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-8" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="activity">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
<a id="blink-9" href="https://amp.dev" role="link" target="_blank" affiliate-link-icon="more-to-read">
amp.devamp.devamp.devamp.devamp.devamp.dev
</a>
</amp-story-grid-layer>
</amp-story-page>

<amp-story-page id="p5">
<amp-story-grid-layer template="vertical">
<h1>Page Four</h1>
<h1>Page Five</h1>
<amp-video
id="vid1"
src="../av/ForBiggerJoyrides-short.mp4"
Expand Down
13 changes: 11 additions & 2 deletions extensions/amp-analytics/0.1/events.js
Expand Up @@ -456,9 +456,18 @@ export class AmpStoryEventTracker extends CustomEventTracker {
const storySpec = config['storySpec'] || {};
const repeat =
storySpec['repeat'] === undefined ? true : storySpec['repeat'];
const pageDetails = vars['pageDetails'];
const eventDetails = vars['eventDetails'];
const tagName = config['tagName'];

if (repeat === false && pageDetails['repeated']) {
if (
tagName &&
eventDetails['tagName'] &&
tagName.toLowerCase() !== eventDetails['tagName']
) {
return;
}

if (repeat === false && eventDetails['repeated']) {
return;
}

Expand Down
6 changes: 3 additions & 3 deletions extensions/amp-analytics/0.1/test/test-events.js
Expand Up @@ -817,7 +817,7 @@ describes.realWin('Events', {amp: 1}, env => {
'storyPageIndex': '0',
'storyPageId': 'p4',
'storyPageCount': '4',
'pageDetails': {'repeated': false},
'eventDetails': {'repeated': false},
};

tracker.add(
Expand All @@ -842,7 +842,7 @@ describes.realWin('Events', {amp: 1}, env => {
'storyPageIndex': '0',
'storyPageId': 'p4',
'storyPageCount': '4',
'pageDetails': {'repeated': true},
'eventDetails': {'repeated': true},
};

tracker.add(target, 'story-page-visible', storyAnalyticsConfig, handler);
Expand All @@ -859,7 +859,7 @@ describes.realWin('Events', {amp: 1}, env => {
'storyPageIndex': '0',
'storyPageId': 'p4',
'storyPageCount': '4',
'pageDetails': {'repeated': true},
'eventDetails': {'repeated': true},
};

tracker.add(target, 'story-page-visible', storyAnalyticsConfig, handler);
Expand Down
26 changes: 22 additions & 4 deletions extensions/amp-story/1.0/amp-story-affiliate-link.js
Expand Up @@ -20,6 +20,7 @@

import {Services} from '../../../src/services';
import {StateProperty, getStoreService} from './amp-story-store-service';
import {StoryAnalyticsEvent, getAnalyticsService} from './story-analytics';
import {getAmpdoc} from '../../../src/service';
import {htmlFor} from '../../../src/static-template';

Expand Down Expand Up @@ -61,6 +62,9 @@ export class AmpStoryAffiliateLink {

/** @private @const {!../../../src/service/resources-interface.ResourcesInterface} */
this.resources_ = Services.resourcesForDoc(getAmpdoc(this.win_.document));

/** @private @const {!./story-analytics.StoryAnalyticsService} */
this.analyticsService_ = getAnalyticsService(this.win_, element);
}

/**
Expand All @@ -80,15 +84,15 @@ export class AmpStoryAffiliateLink {
this.addLaunchElement_();
});

this.initializeListener_();
this.initializeListeners_();
this.element_[AFFILIATE_LINK_BUILT] = true;
}

/**
* Initialize listener to toggle expanded state.
* Initializes listeners.
* @private
*/
initializeListener_() {
initializeListeners_() {
this.storeService_.subscribe(
StateProperty.AFFILIATE_LINK_STATE,
elementToToggleExpand => {
Expand All @@ -98,9 +102,23 @@ export class AmpStoryAffiliateLink {
this.launchEl_.toggleAttribute('hidden', !expand);
if (expand) {
this.element_.toggleAttribute('pristine', false);
this.analyticsService_.triggerEvent(
StoryAnalyticsEvent.FOCUS,
this.element_
);
}
}
);

this.element_.addEventListener('click', event => {
if (this.element_.hasAttribute('expanded')) {
event.stopPropagation();
this.analyticsService_.triggerEvent(
StoryAnalyticsEvent.CLICK_THROUGH,
this.element_
);
}
});
}

/**
Expand All @@ -114,7 +132,7 @@ export class AmpStoryAffiliateLink {
<div class="i-amphtml-story-reset i-amphtml-hidden">
<span class="i-amphtml-story-affiliate-link-text" hidden></span>
<i class="i-amphtml-story-affiliate-link-launch" hidden></i>
</div>
</div>
</div>`;
this.element_.appendChild(iconEl);
}
Expand Down
25 changes: 24 additions & 1 deletion extensions/amp-story/1.0/amp-story-embedded-component.js
Expand Up @@ -22,7 +22,11 @@ import {
UIType,
getStoreService,
} from './amp-story-store-service';
import {AdvancementMode} from './story-analytics';
import {
AdvancementMode,
StoryAnalyticsEvent,
getAnalyticsService,
} from './story-analytics';
import {CSS} from '../../../build/amp-story-tooltip-1.0.css';
import {EventType, dispatch} from './events';
import {LocalizedStringId} from '../../../src/localized-strings';
Expand Down Expand Up @@ -286,6 +290,9 @@ export class AmpStoryEmbeddedComponent {
/** @private @const {!../../../src/service/resources-interface.ResourcesInterface} */
this.resources_ = Services.resourcesForDoc(getAmpdoc(this.win_.document));

/** @private @const {!./story-analytics.StoryAnalyticsService} */
this.analyticsService_ = getAnalyticsService(this.win_, storyEl);

/** @private @const {!../../../src/service/owners-interface.OwnersInterface} */
this.owners_ = Services.ownersForDoc(getAmpdoc(this.win_.document));

Expand Down Expand Up @@ -384,6 +391,10 @@ export class AmpStoryEmbeddedComponent {
case EmbeddedComponentState.FOCUSED:
this.state_ = state;
this.onFocusedStateUpdate_(component);
this.analyticsService_.triggerEvent(
StoryAnalyticsEvent.FOCUS,
this.triggeringTarget_
);
break;
case EmbeddedComponentState.HIDDEN:
this.state_ = state;
Expand Down Expand Up @@ -503,6 +514,18 @@ export class AmpStoryEmbeddedComponent {
this.onOutsideTooltipClick_(event)
);

this.tooltip_.addEventListener(
'click',
event => {
event.stopPropagation();
this.analyticsService_.triggerEvent(
StoryAnalyticsEvent.CLICK_THROUGH,
this.triggeringTarget_
);
},
true /** capture */
);

return this.shadowRoot_;
}

Expand Down
1 change: 1 addition & 0 deletions extensions/amp-story/1.0/page-advancement.js
Expand Up @@ -552,6 +552,7 @@ class ManualAdvancement extends AdvancementConfig {
const pageRect = this.element_.getLayoutBox();

if (this.isHandledByEmbeddedComponent_(event, pageRect)) {
event.stopPropagation();
event.preventDefault();
const embedComponent = /** @type {InteractiveComponentDef} */ (this.storeService_.get(
StateProperty.INTERACTIVE_COMPONENT_STATE
Expand Down
16 changes: 12 additions & 4 deletions extensions/amp-story/1.0/story-analytics.js
Expand Up @@ -25,6 +25,8 @@ export const StoryAnalyticsEvent = {
BOOKEND_CLICK: 'story-bookend-click',
BOOKEND_ENTER: 'story-bookend-enter',
BOOKEND_EXIT: 'story-bookend-exit',
CLICK_THROUGH: 'story-click-through',
FOCUS: 'story-focus',
LAST_PAGE_VISIBLE: 'story-last-page-visible',
PAGE_ATTACHMENT_ENTER: 'story-page-attachment-enter',
PAGE_ATTACHMENT_EXIT: 'story-page-attachment-exit',
Expand Down Expand Up @@ -127,23 +129,25 @@ export class StoryAnalyticsService {

/**
* @param {!StoryAnalyticsEvent} eventType
* @param {Element=} element
*/
triggerEvent(eventType) {
triggerEvent(eventType, element = null) {
this.incrementPageEventCount_(eventType);
triggerAnalyticsEvent(
this.element_,
eventType,
this.updateDetails(eventType)
this.updateDetails(eventType, element)
);
}

/**
* Updates event details.
* @param {!StoryAnalyticsEvent} eventType
* @param {Element=} element
* @visibleForTesting
* @return {!JsonObject}}
*/
updateDetails(eventType) {
updateDetails(eventType, element = null) {
const details = {};
const vars = this.variableService_.get();
const pageId = vars['storyPageId'];
Expand All @@ -152,8 +156,12 @@ export class StoryAnalyticsService {
details.repeated = true;
}

if (element) {
details.tagName = element.tagName.toLowerCase();
}

return /** @type {!JsonObject} */ (Object.assign(
{pageDetails: details},
{eventDetails: details},
vars
));
}
Expand Down
4 changes: 2 additions & 2 deletions extensions/amp-story/1.0/test/test-analytics.js
Expand Up @@ -70,7 +70,7 @@ describes.fakeWin('amp-story analytics', {}, env => {
expect(trigger).to.have.been.calledOnceWith('story-page-visible');

const details = analytics.updateDetails('story-page-visible');
expect(details.pageDetails).to.deep.equal({});
expect(details.eventDetails).to.deep.equal({});
});

it('should mark event as repeated when fired more than once', () => {
Expand All @@ -94,7 +94,7 @@ describes.fakeWin('amp-story analytics', {}, env => {
expect(trigger).to.have.been.calledWith('story-page-visible');
expect(trigger).to.have.been.calledThrice;
expect(
analytics.updateDetails('story-page-visible').pageDetails
analytics.updateDetails('story-page-visible').eventDetails
).to.deep.include({
'repeated': true,
});
Expand Down

0 comments on commit 3c4bd04

Please sign in to comment.