Skip to content

Commit

Permalink
make pageview() method detect listings if the page url has the y_sour…
Browse files Browse the repository at this point in the history
…ce param present
  • Loading branch information
benmcginnis committed Aug 1, 2022
1 parent 6cc9553 commit 28c634c
Show file tree
Hide file tree
Showing 24 changed files with 280 additions and 67 deletions.
13 changes: 13 additions & 0 deletions docs/analytics.commonconversiondata.cookieid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [CommonConversionData](./analytics.commonconversiondata.md) &gt; [cookieId](./analytics.commonconversiondata.cookieid.md)

## CommonConversionData.cookieId property

A cookie id from a first party cookie (i.e. from a visit to a domain you control)

<b>Signature:</b>

```typescript
cookieId: string;
```
21 changes: 21 additions & 0 deletions docs/analytics.commonconversiondata.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [CommonConversionData](./analytics.commonconversiondata.md)

## CommonConversionData interface

Shared properties of both ConversionEvent and ListingsClickEvent

<b>Signature:</b>

```typescript
export interface CommonConversionData
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [cookieId](./analytics.commonconversiondata.cookieid.md) | string | A cookie id from a first party cookie (i.e. from a visit to a domain you control) |
| [referrer?](./analytics.commonconversiondata.referrer.md) | string | <i>(Optional)</i> Page which sent the user to the current page, comes from typically Document.referrer |

13 changes: 13 additions & 0 deletions docs/analytics.commonconversiondata.referrer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [CommonConversionData](./analytics.commonconversiondata.md) &gt; [referrer](./analytics.commonconversiondata.referrer.md)

## CommonConversionData.referrer property

Page which sent the user to the current page, comes from typically Document.referrer

<b>Signature:</b>

```typescript
referrer?: string;
```
13 changes: 13 additions & 0 deletions docs/analytics.conversiondetails.cid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [ConversionDetails](./analytics.conversiondetails.md) &gt; [cid](./analytics.conversiondetails.cid.md)

## ConversionDetails.cid property

The id of the conversion tag, you can find the value from the conversion tracking section in your Yext account. You can find a list of tags under: https://www.yext.com/s/\[your business id\]/reports/conversiontracking/setup

<b>Signature:</b>

```typescript
cid: string;
```
13 changes: 13 additions & 0 deletions docs/analytics.conversiondetails.cv.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [ConversionDetails](./analytics.conversiondetails.md) &gt; [cv](./analytics.conversiondetails.cv.md)

## ConversionDetails.cv property

Conversion Value Optional custom value supplied for this conversion

<b>Signature:</b>

```typescript
cv?: string;
```
21 changes: 21 additions & 0 deletions docs/analytics.conversiondetails.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [ConversionDetails](./analytics.conversiondetails.md)

## ConversionDetails interface

The details of an individual conversion event, without the cookie id.

<b>Signature:</b>

```typescript
export interface ConversionDetails
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [cid](./analytics.conversiondetails.cid.md) | string | The id of the conversion tag, you can find the value from the conversion tracking section in your Yext account. You can find a list of tags under: https://www.yext.com/s/\[your business id\]/reports/conversiontracking/setup |
| [cv?](./analytics.conversiondetails.cv.md) | string | <i>(Optional)</i> Conversion Value Optional custom value supplied for this conversion |

2 changes: 1 addition & 1 deletion docs/analytics.conversionevent.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ An event representing a Conversion
```typescript
export interface ConversionEvent extends CommonConversionData, ConversionDetails
```
<b>Extends:</b> CommonConversionData, ConversionDetails
<b>Extends:</b> [CommonConversionData](./analytics.commonconversiondata.md)<!-- -->, [ConversionDetails](./analytics.conversiondetails.md)
2 changes: 1 addition & 1 deletion docs/analytics.listingsclickevent.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ An event representing a user arriving at a landing page from a publisher site.
```typescript
export interface ListingsClickEvent extends CommonConversionData
```
<b>Extends:</b> CommonConversionData
<b>Extends:</b> [CommonConversionData](./analytics.commonconversiondata.md)
## Properties
Expand Down
2 changes: 2 additions & 0 deletions docs/analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
| [AnalyticsPayload](./analytics.analyticspayload.md) | The shape of the data which is sent during an analytics request. |
| [AutocompleteEvent](./analytics.autocompleteevent.md) | Event for autocomplete selection. |
| [BaseAnalyticsConfig](./analytics.baseanalyticsconfig.md) | Base analytics configuration |
| [CommonConversionData](./analytics.commonconversiondata.md) | Shared properties of both ConversionEvent and ListingsClickEvent |
| [ConversionDetails](./analytics.conversiondetails.md) | The details of an individual conversion event, without the cookie id. |
| [ConversionEvent](./analytics.conversionevent.md) | An event representing a Conversion |
| [ConversionTrackingService](./analytics.conversiontrackingservice.md) | A service for tracking conversions |
| [CtaEvent](./analytics.ctaevent.md) | A call to action analytics event. |
Expand Down
2 changes: 1 addition & 1 deletion docs/analytics.pagesanalyticsconfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface PagesAnalyticsConfig extends BaseAnalyticsConfig
| Property | Type | Description |
| --- | --- | --- |
| [pageType](./analytics.pagesanalyticsconfig.pagetype.md) | [DirectoryPage](./analytics.directorypage.md) \| [EntityPage](./analytics.entitypage.md) \| [LocatorPage](./analytics.locatorpage.md) \| [StaticPage](./analytics.staticpage.md) | The details of the page type |
| [path](./analytics.pagesanalyticsconfig.path.md) | string | The path component of the page url |
| [pageUrl](./analytics.pagesanalyticsconfig.pageurl.md) | string | The full url of the page we are on, typically window.location.href |
| [production](./analytics.pagesanalyticsconfig.production.md) | boolean | Set to true if the environment is production If set to true events will appear in Analytics Reports in your Yext Account |
| [referrer](./analytics.pagesanalyticsconfig.referrer.md) | string | Page which sent the user to the current page, comes from typically Document.referrer |
| [siteId](./analytics.pagesanalyticsconfig.siteid.md) | number | The ID of the Pages Site Can be easily found from the url of the Deploy Page in your Yext Account e.g. https://www.yext.com/s/\[businessId\]/yextsites/\[siteid\]/branch/\[branchId\]/deploys/recent |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [PagesAnalyticsConfig](./analytics.pagesanalyticsconfig.md) &gt; [path](./analytics.pagesanalyticsconfig.path.md)
[Home](./index.md) &gt; [@yext/analytics](./analytics.md) &gt; [PagesAnalyticsConfig](./analytics.pagesanalyticsconfig.md) &gt; [pageUrl](./analytics.pagesanalyticsconfig.pageurl.md)

## PagesAnalyticsConfig.path property
## PagesAnalyticsConfig.pageUrl property

The path component of the page url
The full url of the page we are on, typically window.location.href

<b>Signature:</b>

```typescript
path: string;
pageUrl: string;
```
2 changes: 1 addition & 1 deletion docs/analytics.pagesanalyticsservice.track.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ track(event: PagesAnalyticsEvent, conversionInfo?: ConversionDetails): Promise<v
| Parameter | Type | Description |
| --- | --- | --- |
| event | [PagesAnalyticsEvent](./analytics.pagesanalyticsevent.md) | the pages event to track |
| conversionInfo | ConversionDetails | Optional parameter to pass with the CID from the conversion tag if this event should represent a conversion and conversion tracking is enabled. |
| conversionInfo | [ConversionDetails](./analytics.conversiondetails.md) | Optional parameter to pass with the CID from the conversion tag if this event should represent a conversion and conversion tracking is enabled. |

<b>Returns:</b>

Expand Down
17 changes: 13 additions & 4 deletions etc/analytics.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,18 @@ export interface BaseAnalyticsConfig {
visitor?: Visitor;
}

// Warning: (ae-forgotten-export) The symbol "CommonConversionData" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "ConversionDetails" needs to be exported by the entry point index.d.ts
//
// @public
export interface CommonConversionData {
cookieId: string;
referrer?: string;
}

// @public
export interface ConversionDetails {
cid: string;
cv?: string;
}

// @public
export interface ConversionEvent extends CommonConversionData, ConversionDetails {
}
Expand Down Expand Up @@ -120,7 +129,7 @@ export interface LocatorPage extends PageType {
// @public
export interface PagesAnalyticsConfig extends BaseAnalyticsConfig {
pageType: DirectoryPage | EntityPage | LocatorPage | StaticPage;
path: string;
pageUrl: string;
production: boolean;
referrer: string;
siteId: number;
Expand Down
4 changes: 2 additions & 2 deletions src/infra/ConversionTrackingReporter.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConversionEvent, COOKIE_PARAM, ListingsClickEvent } from '../models';
import { DEFAULT_CONVERSION_TRACKING_DOMAIN } from '../models/constants';
import { DEFAULT_CONVERSION_TRACKING_DOMAIN, LISTINGS_SOURCE_PARAM } from '../models/constants';
import { CommonConversionData } from '../models/conversiontracking/CommonConversionData';
import { ConversionTrackingService, HttpRequesterService } from '../services';
import { calculateSeed } from './CalculateSeed';
Expand Down Expand Up @@ -60,7 +60,7 @@ export class ConversionTrackingReporter implements ConversionTrackingService {
async trackListings(event: ListingsClickEvent): Promise<void> {
const url = new URL(`https://${DEFAULT_CONVERSION_TRACKING_DOMAIN}/${listingsEndpoint}`);
const params = new URLSearchParams();
params.set('y_source', event.source);
params.set(LISTINGS_SOURCE_PARAM, event.source);
params.set('location', event.location);
ConversionTrackingReporter.formatBaseEvent(event, params);
url.search = params.toString();
Expand Down
27 changes: 24 additions & 3 deletions src/infra/PagesAnalyticsReporter.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { COOKIE_PARAM, DEFAULT_CONVERSION_TRACKING_DOMAIN } from '../models/constants';
import { COOKIE_PARAM, DEFAULT_CONVERSION_TRACKING_DOMAIN, LISTINGS_SOURCE_PARAM } from '../models/constants';
import { ConversionDetails } from '../models/conversiontracking/ConversionDetails';
import { HttpRequesterService, PagesAnalyticsService } from '../services';
import { DefaultPagesEventNames, PagesAnalyticsConfig, Visitor } from '../models';
Expand Down Expand Up @@ -55,12 +55,20 @@ export class PagesAnalyticsReporter implements PagesAnalyticsService{
private _debug: boolean|undefined;
private _conversionTrackingEnabled: boolean|undefined;
private _cookieID: string|undefined;
private _conversionTracker: ConversionTrackingReporter;
private readonly _conversionTracker: ConversionTrackingReporter;
private _hasTrackedListings: boolean;
private readonly _pageUrl: URL;
constructor(private config: PagesAnalyticsConfig,
private httpRequesterService: HttpRequesterService) {
this.setVisitor(config.visitor);
this._debug = config.debug;
this._conversionTracker = new ConversionTrackingReporter(this.httpRequesterService, this._debug);
this._hasTrackedListings = false;
try {
this._pageUrl = new URL(config.pageUrl);
} catch {
throw new Error(`pageUrl property must be a valid URL, was: '${config.pageUrl}'`);
}
}

/**
Expand Down Expand Up @@ -102,7 +110,7 @@ export class PagesAnalyticsReporter implements PagesAnalyticsService{
}

params.set(urlParamNames.CacheBuster, calculateSeed().toString());
params.set(urlParamNames.UrlPath, this.config.path);
params.set(urlParamNames.UrlPath, this._pageUrl.pathname);
params.set(urlParamNames.Referrer, this.config.referrer);

if (this._conversionTrackingEnabled && this._cookieID) {
Expand All @@ -119,6 +127,19 @@ export class PagesAnalyticsReporter implements PagesAnalyticsService{

/** {@inheritDoc PagesAnalyticsService.pageView} */
async pageView(): Promise<void> {
const sourceValue = this._pageUrl.searchParams.get(LISTINGS_SOURCE_PARAM);

if (this._conversionTrackingEnabled
&& this._cookieID
&& !this._hasTrackedListings
&& sourceValue) {
await this._conversionTracker.trackListings({
cookieId: this._cookieID,
location: this._pageUrl.toString(),
source: sourceValue,
});
this._hasTrackedListings = true;
}
return this.track(PageViewEvent);
}

Expand Down
4 changes: 2 additions & 2 deletions src/models/config/PagesAnalyticsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export interface PagesAnalyticsConfig extends BaseAnalyticsConfig {
production: boolean,

/**
* The path component of the page url
* The full url of the page we are on, typically window.location.href
*/
path: string
pageUrl: string

/**
* Page which sent the user to the current page, comes from typically Document.referrer
Expand Down
1 change: 1 addition & 0 deletions src/models/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
* @public
*/
export const COOKIE_PARAM = '_yfpc';
export const LISTINGS_SOURCE_PARAM = 'y_source';
export const DEFAULT_CONVERSION_TRACKING_DOMAIN = 'realtimeanalytics.yext.com';
2 changes: 2 additions & 0 deletions src/models/conversiontracking/CommonConversionData.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/**
* Shared properties of both ConversionEvent and ListingsClickEvent
*
* @public
*/
export interface CommonConversionData {
/**
Expand Down
2 changes: 2 additions & 0 deletions src/models/conversiontracking/ConversionDetails.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
/**
* The details of an individual conversion event, without the cookie id.
*
* @public
*/
export interface ConversionDetails {
/**
Expand Down
10 changes: 6 additions & 4 deletions src/services/__mocks__/MockHttpRequesterService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import 'isomorphic-fetch';
import { HttpRequesterService } from '../HttpRequesterService';

export const mockHttpRequesterService: HttpRequesterService = {
post: jest.fn(() => Promise.resolve(new Response())),
get: jest.fn(() => Promise.resolve(new Response())),
};
export function mockHttpRequesterService(): HttpRequesterService {
return {
post: jest.fn(() => Promise.resolve(new Response())),
get: jest.fn(() => Promise.resolve(new Response())),
};
}

export function mockErrorHttpRequesterService(message: string): HttpRequesterService {
return {
Expand Down
4 changes: 2 additions & 2 deletions test-site/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ const pages = providePagesAnalytics({
pageType: {
name: 'entity',
pageSetId: 'location',
id: '18718615',
id: 18718615,
},
referrer: 'https://www.google.com',
path: '/location/11291',
pageUrl: 'https://www.pagesanalyticstesting.com/location/11291?y_source=123353131212312312',
businessId: 3350634,
production: false,
siteId: 40659,
Expand Down
18 changes: 12 additions & 6 deletions tests/infra/ConversionTrackingReporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,27 @@ beforeEach(() => {
jest.spyOn(global.Date, 'now').mockReturnValue(1);
});

const reporter = new ConversionTrackingReporter(mockHttpRequesterService);

it('should not set empty parameters', () => {
const mockService = mockHttpRequesterService();
const reporter = new ConversionTrackingReporter(mockService);
reporter.trackConversion({
cid: '12345',
cookieId: '54321',
});
expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(
expect(mockService.get).toHaveBeenLastCalledWith(
'https://realtimeanalytics.yext.com/conversiontracking/conversion?cid=12345&_yfpc=54321&v=1001',
);
});

it('should set all parameters passed', () => {
const mockService = mockHttpRequesterService();
const reporter = new ConversionTrackingReporter(mockService);
reporter.trackConversion({
cid: '12345',
cookieId: '54321',
referrer: 'http://www.google.com/foo/bar',
});
expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(
expect(mockService.get).toHaveBeenLastCalledWith(
'https://realtimeanalytics.yext.com/conversiontracking/conversion?cid=12345&_yfpc=54321&referrer=http%3A%2F%2Fwww.google.com%2Ffoo%2Fbar&v=1001',
);
});
Expand All @@ -42,24 +44,28 @@ it('should handle an error', () => {
});

it('should track listings', () => {
const mockService = mockHttpRequesterService();
const reporter = new ConversionTrackingReporter(mockService);
reporter.trackListings({
cookieId: '54321',
source: 'foo',
location: 'https://www.example.com/my/foo/page'
});
expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(
expect(mockService.get).toHaveBeenLastCalledWith(
'https://realtimeanalytics.yext.com/listings?y_source=foo&location=https%3A%2F%2Fwww.example.com%2Fmy%2Ffoo%2Fpage&_yfpc=54321&v=1001',
);
});

it('should track listings with more details', () => {
const mockService = mockHttpRequesterService();
const reporter = new ConversionTrackingReporter(mockService);
reporter.trackListings({
source: 'foo',
location: 'https://www.example.com/my/foo/page',
cookieId: '54321',
referrer: 'http://www.google.com/foo/bar',
});
expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(
expect(mockService.get).toHaveBeenLastCalledWith(
'https://realtimeanalytics.yext.com/listings?y_source=foo&location=https%3A%2F%2Fwww.example.com%2Fmy%2Ffoo%2Fpage&_yfpc=54321&referrer=http%3A%2F%2Fwww.google.com%2Ffoo%2Fbar&v=1001',
);
});

0 comments on commit 28c634c

Please sign in to comment.