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

implement conversion tracking service #29

Merged
merged 11 commits into from
Aug 9, 2022
Merged

Conversation

benmcginnis
Copy link
Member

@benmcginnis benmcginnis commented Jul 29, 2022

Adds Conversion Tracking to the Analytics Library, including:

  • New standalone ConversionTrackingReporter
  • Additions to PagesAnalyticsReporter to allow it to track conversions using the ConversionTrackingReporter as well as properly credit Listings and Pages for conversions that happen later
  • Adds a CookieManager utility class that can be used by implementers to retrieve the Yext cookieId and set it if need be.

Copy link
Contributor

@AjayBenno AjayBenno left a comment

Choose a reason for hiding this comment

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

Left a few comments on required parameters(if that influences any preconditions we want to enforce client side) and some questions.

async trackConversion(event: ConversionEvent): Promise<void> {
const url = new URL(`https://${DEFAULT_CONVERSION_TRACKING_DOMAIN}/${conversionEndpoint}`);
const params = new URLSearchParams();
params.set('cid', event.cid);
Copy link
Contributor

Choose a reason for hiding this comment

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

A note, CID id a required parameter if we want so the server will 400 if this doesn't exist.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, it's marked required on the ConversionEvent interface

}

/** {@inheritDoc ConversionTrackingService.trackConversion} */
async trackConversion(event: ConversionEvent): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Note we also need to pass a location field for the conversion event as well(its should be the same as the listings location param(currently for ytag it comes from window.location.href)

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't see that on the required param for the conversion event itself, just the listingsclickevent in the docs, it's not even listed as an optional parameter on the conversion event: https://www.yext.com/docmd/docs/src/com/yext/analytics/events/conversions.html

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah yea location is a new param we added in the last few months for conversions(its not required for the event to work though). Its mainly to support our new analytics events pipeline. I'll update those docs.

}

/** {@inheritDoc ConversionTrackingService.trackListings} */
async trackListings(event: ListingsClickEvent): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious, how is this expected to be used? I'm reading through the ytag code and the listings stuff has some special logic where it only fires once upon load.

Copy link
Member Author

Choose a reason for hiding this comment

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

So some of the borders of this library are a bit weird because it's meant to be useable server side. I need to think about the pageView method and what it should provide implementers to tell them to remove the listings parameter from the pageurl if necessary. Any thoughts? I can pull the listings crediting out of the pageView method so that it's entirely on the implementer to do and add that logic into yext/pages (seems like that might be best). I could also add something to utils for implementers to use to manage that state

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh i see the code in PagesAnalyticsReporter where it does the only fire once logic. I think we might actually be ok with what logic already exists there, it seems that on the ytag implementation refreshing the page would cause the listings event to fire again.

Up to you if you want to move it out right now, think it should be ok.

Copy link
Member Author

Choose a reason for hiding this comment

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

oh cool I was just looking at ytag and hadn't seen your comment and yeah I agree it doesn't seem to handle page refreshes. I can add a TODO to handle that in the future

async trackListings(event: ListingsClickEvent): Promise<void> {
const url = new URL(`https://${DEFAULT_CONVERSION_TRACKING_DOMAIN}/${listingsEndpoint}`);
const params = new URLSearchParams();
params.set(LISTINGS_SOURCE_PARAM, event.source);
Copy link
Contributor

Choose a reason for hiding this comment

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

Also note, /listings will throw a server error if y_source is not set

Copy link
Member Author

Choose a reason for hiding this comment

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

it's required by the ListingsClickEvent

}
}

private static formatBaseEvent(event: CommonConversionData, params: URLSearchParams): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

Are we only dealing with first party cookies for sites?

Copy link
Member Author

Choose a reason for hiding this comment

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

after discussing with @maperalta the cookieId is either the first or the third party cookie. This library doesn't send anything in the headers as it doesn't have direct access to the Document, which is why it seems a bit weird.

If you look at CookieManager in utils that has the cookie retrieval logic from ytag and in yext/pages I'm using it like this:

  enableConversionTracking(): void {
    if (this.canTrack()) {
      this._cookieManager = new CookieManager();
      this._analyticsReporter?.setConversionTrackingEnabled(
        true,
        this._cookieManager.setAndGetYextCookie(),
      );
    }
  }

Copy link
Member Author

Choose a reason for hiding this comment

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

let me also tag a WIP PR for yext/pages so you can see the implementation on the front end

Copy link
Member Author

Choose a reason for hiding this comment

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

@benmcginnis benmcginnis merged commit 8d2ef1e into pages/trunk Aug 9, 2022
@benmcginnis benmcginnis deleted the conversiontracking branch August 9, 2022 14:11
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

3 participants