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

feat(store_pagespixel): add legacy analytics support #28

Merged
merged 25 commits into from
Jul 28, 2022

Conversation

tatimblin
Copy link
Contributor

J=CR-2409

@tatimblin
Copy link
Contributor Author

tatimblin commented Jul 15, 2022

This adds two new AnalyticsEvent types 'PAGE_VIEW' and 'CLICK_EVENT', which get directed to an alternate fetch request. Here is an example usage

      <a
        href="https://yext.com"
        target="_blank"
        onClick={() => analytics.report({
          type: 'CLICK_EVENT',
          product: 'storepages',
          v: 1654287242049,
          pageurl: '%2Fmd%2Feldersburg%2Fbrenda-given',
          pagesReferrer: 'https%3A%2F%2Fbankers_amerisbank_com.yextpages.net%2Fmd%2Feldersburg',
          businessids: 3371543,
          siteId: 31196,
          isStaging: true,
          ids: 34233156,
          pageSetId: 'Locations',
          eventType: 'yext_sites_test',
        })}
      >
        Yext analytics
      </a>

Currently you have to pass everything into the event, but some of the stuff can be done automatically.

  1. 'product' will always be 'storepages' so it can be hardcoded
  2. pageurl and pagesReferrer could be determined from window
  3. businessids is available in the config
  4. isStaging, pageSetId, and eventType could probably be derived from the application

Additionally the config would need to be updated to take 1 of 2 config types, currently some answers values are required.

  const analytics = provideAnalytics({
    experienceKey: 'yext-inventory',
    experienceVersion: 'PRODUCTION',
    businessId: 2987593,
  });

Additionally wanted to share our thoughts on the timeline of this. Once pages analytics are updated to the same system as answers, we'd like users to interact with yext analytics the same way regardless of product. This update aims to stand in and let us construct requests as if it that new system was ready so that when it is, reportLegacy can be removed and existing sites just need to upgrade this package in each repo to switch over.

const reporter = new PagesAnalyticsReporter(config, mockHttpRequesterService);
reporter.pageView();
const expectedUrl = '';
expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl, expect.anything());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm getting a weird failure trying to run this:


 FAIL  tests/infra/PagesAnalyticsReporter.ts
  ● Test suite failed to run

    TypeError: Cannot read properties of undefined (reading 'generatedLine')

      at compareByGeneratedPositionsDeflated (node_modules/source-map-support/node_modules/source-map/lib/util.js:344:47)
      at doQuickSort (node_modules/source-map-support/node_modules/source-map/lib/quick-sort.js:88:11)
      at Object.<anonymous>.exports.quickSort (node_modules/source-map-support/node_modules/source-map/lib/quick-sort.js:113:3)
      at BasicSourceMapConsumer.SourceMapConsumer_parseMappings [as _parseMappings] (node_modules/source-map-support/node_modules/source-map/lib/source-map-consumer.js:564:5)
      at BasicSourceMapConsumer.get [as _generatedMappings] (node_modules/source-map-support/node_modules/source-map/lib/source-map-consumer.js:70:12)
      at BasicSourceMapConsumer.SourceMapConsumer_originalPositionFor [as originalPositionFor] (node_modules/source-map-support/node_modules/source-map/lib/source-map-consumer.js:655:12)
      at mapSourcePosition (node_modules/source-map-support/source-map-support.js:244:42)
      at wrapCallSite (node_modules/source-map-support/source-map-support.js:397:20)
      at Function.prepareStackTrace (node_modules/source-map-support/source-map-support.js:446:39)



README.md Outdated
businessId: 123456, // this comes from the url of your Yext account
featureId: 'My Locator', // the name of the feature in your features.json
pageType: 'locator', // the type of page, can be 'entity', 'directory', 'locator', or 'static'
product: 'storepages',

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What should product be? If it's always storepages, is there a reason they need to specify it?

README.md Outdated
featureId: 'My Locator', // the name of the feature in your features.json
pageType: 'locator', // the type of page, can be 'entity', 'directory', 'locator', or 'static'
product: 'storepages',
production: false, // set to true if you are in the production environment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Production is a pretty overloaded term for us. Is this production as in the production vs staging deploy? Or production vs. sandbox? Could also see someone confusing this with the Production answers experience tag.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point... it's just that staging doesn't exist anymore so I figured it made sense to flip the bit

README.md Outdated

```ts
import { provideAnalytics } from '@yext/analytics';

const analytics = provideAnalytics({
experienceKey: '<your experience key>',
experienceVersion: 'PRODUCTION',
businessId: 123456,
businessId: 123456, // this comes from the url of your Yext account
featureId: 'My Locator', // the name of the feature in your features.json

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you're using the react code features.json is autogenerated and you may never look at it, might need to specify that the name in that case is taken from the file name of your entry template

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

README.md Outdated
product: 'storepages',
production: false, // set to true if you are in the production environment
siteId: 654321, // the id of your site, you can find this in the url of your deploy page
ids: [90210], // if your pageType is 'entity' this is required, and it is the uid of the entity

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this required on directory pages (or if it's optional, is there a benefit to providing it?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in sites, it's necessary to identify the directory entity, since directory pages are entity pages

@@ -129,6 +119,61 @@ export interface CtaEvent {
// @public
export type EnumOrString<T extends string> = T | `${T}`;

// Warning: (ae-forgotten-export) The symbol "BaseAnalyticsConfig" needs to be exported by the entry point index.d.ts

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this warning something we need to do something about?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think i've fixed this

src/infra/HttpRequester.ts Show resolved Hide resolved

constructor(config: PagesAnalyticsConfig, event: PagesEvent) {
this.eventType = event.eventType;
this.product = 'storepages';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this intentionally hardcoded instead of reading from the config?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed this from the config as it is only ever "storepages" in the context of this library

this.ids = config.ids;
this.pageType = config.pageType;

if (this.pageType === 'entity' && !this.ids) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we want I believe this is enforceable at the type level. Do we also want to check the opposite, that entityIds aren't provided for non 'entity' page types?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not 100% certain. I believe they are optional, for example if you click on a result on a locator i think we can pass the entity id. I haven't had a chance to check

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i've confirmed that if you set the id currently it treats it as an entity page


this.featureId = config.featureId;
this.pagesReferrer = config.pagesReferrer ? config.pagesReferrer : window.document.referrer;
this.path = config.path ? config.path : window.location.pathname;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question about references to window


/**
* Reports a user interaction event.
* Will perform a promis rejection if the API contains an error or if

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Will perform a promis rejection if the API contains an error or if
* Will perform a promise rejection if the API contains an error or if

import fetch from 'cross-fetch';

/**
* Responsible for making web requests.
*
* @public
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be annotated as public? Ideally it should just be an internal implementation detail.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So i did this because there was a warning in the auto-generated markdown file bc this is part of the method signature of the AnalyticsReporters

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the warning is:

// Warning: (ae-forgotten-export) The symbol "HttpRequesterService" needs to be exported by the entry point index.d.ts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do the various reporters need to be exported? We treated the AnalyticsReporter as an implementation detail, IIRC. We did not export it, users could not instantiate it manually. They had to use the provide method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me look back at master, i thought I was following what it was doing but I may have over-exported things

/**
* A service for sending requests on the web.
*
* @public
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing about this being public.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thing about the method signatures

@@ -3,7 +3,7 @@
*
* @public
*/
export enum AnalyticsEventType {
export enum SearchAnalyticsEventType {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If AnalyticsEventType was exported by the library, we will need an alias.

@tmeyer2115 tmeyer2115 self-requested a review July 28, 2022 18:37
@benmcginnis benmcginnis merged commit 90e1daa into pages/trunk Jul 28, 2022
@benmcginnis benmcginnis deleted the pages/doit branch July 28, 2022 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants