diff --git a/docs/analytics.commonconversiondata.cookieid.md b/docs/analytics.commonconversiondata.cookieid.md
new file mode 100644
index 00000000..e7c676f1
--- /dev/null
+++ b/docs/analytics.commonconversiondata.cookieid.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [CommonConversionData](./analytics.commonconversiondata.md) > [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)
+
+Signature:
+
+```typescript
+cookieId: string;
+```
diff --git a/docs/analytics.commonconversiondata.md b/docs/analytics.commonconversiondata.md
new file mode 100644
index 00000000..c2f1299e
--- /dev/null
+++ b/docs/analytics.commonconversiondata.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [CommonConversionData](./analytics.commonconversiondata.md)
+
+## CommonConversionData interface
+
+Shared properties of both ConversionEvent and ListingsClickEvent
+
+Signature:
+
+```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 | (Optional) Page which sent the user to the current page, comes from typically Document.referrer |
+
diff --git a/docs/analytics.commonconversiondata.referrer.md b/docs/analytics.commonconversiondata.referrer.md
new file mode 100644
index 00000000..be39e398
--- /dev/null
+++ b/docs/analytics.commonconversiondata.referrer.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [CommonConversionData](./analytics.commonconversiondata.md) > [referrer](./analytics.commonconversiondata.referrer.md)
+
+## CommonConversionData.referrer property
+
+Page which sent the user to the current page, comes from typically Document.referrer
+
+Signature:
+
+```typescript
+referrer?: string;
+```
diff --git a/docs/analytics.conversiondetails.cid.md b/docs/analytics.conversiondetails.cid.md
new file mode 100644
index 00000000..cd230937
--- /dev/null
+++ b/docs/analytics.conversiondetails.cid.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [ConversionDetails](./analytics.conversiondetails.md) > [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
+
+Signature:
+
+```typescript
+cid: string;
+```
diff --git a/docs/analytics.conversiondetails.cv.md b/docs/analytics.conversiondetails.cv.md
new file mode 100644
index 00000000..e93de409
--- /dev/null
+++ b/docs/analytics.conversiondetails.cv.md
@@ -0,0 +1,13 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [ConversionDetails](./analytics.conversiondetails.md) > [cv](./analytics.conversiondetails.cv.md)
+
+## ConversionDetails.cv property
+
+Conversion Value Optional custom value supplied for this conversion
+
+Signature:
+
+```typescript
+cv?: string;
+```
diff --git a/docs/analytics.conversiondetails.md b/docs/analytics.conversiondetails.md
new file mode 100644
index 00000000..2e72d041
--- /dev/null
+++ b/docs/analytics.conversiondetails.md
@@ -0,0 +1,21 @@
+
+
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [ConversionDetails](./analytics.conversiondetails.md)
+
+## ConversionDetails interface
+
+The details of an individual conversion event, without the cookie id.
+
+Signature:
+
+```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 | (Optional) Conversion Value Optional custom value supplied for this conversion |
+
diff --git a/docs/analytics.conversionevent.md b/docs/analytics.conversionevent.md
index 2fdd37d9..0b5976e8 100644
--- a/docs/analytics.conversionevent.md
+++ b/docs/analytics.conversionevent.md
@@ -11,5 +11,5 @@ An event representing a Conversion
```typescript
export interface ConversionEvent extends CommonConversionData, ConversionDetails
```
-Extends: CommonConversionData, ConversionDetails
+Extends: [CommonConversionData](./analytics.commonconversiondata.md), [ConversionDetails](./analytics.conversiondetails.md)
diff --git a/docs/analytics.listingsclickevent.md b/docs/analytics.listingsclickevent.md
index 9c7747ba..db36dec9 100644
--- a/docs/analytics.listingsclickevent.md
+++ b/docs/analytics.listingsclickevent.md
@@ -11,7 +11,7 @@ An event representing a user arriving at a landing page from a publisher site.
```typescript
export interface ListingsClickEvent extends CommonConversionData
```
-Extends: CommonConversionData
+Extends: [CommonConversionData](./analytics.commonconversiondata.md)
## Properties
diff --git a/docs/analytics.md b/docs/analytics.md
index 90ea0e5d..5df45137 100644
--- a/docs/analytics.md
+++ b/docs/analytics.md
@@ -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. |
diff --git a/docs/analytics.pagesanalyticsconfig.md b/docs/analytics.pagesanalyticsconfig.md
index 7121d8fa..b1a97da6 100644
--- a/docs/analytics.pagesanalyticsconfig.md
+++ b/docs/analytics.pagesanalyticsconfig.md
@@ -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 |
diff --git a/docs/analytics.pagesanalyticsconfig.path.md b/docs/analytics.pagesanalyticsconfig.pageurl.md
similarity index 56%
rename from docs/analytics.pagesanalyticsconfig.path.md
rename to docs/analytics.pagesanalyticsconfig.pageurl.md
index 21e03f58..3cab101f 100644
--- a/docs/analytics.pagesanalyticsconfig.path.md
+++ b/docs/analytics.pagesanalyticsconfig.pageurl.md
@@ -1,13 +1,13 @@
-[Home](./index.md) > [@yext/analytics](./analytics.md) > [PagesAnalyticsConfig](./analytics.pagesanalyticsconfig.md) > [path](./analytics.pagesanalyticsconfig.path.md)
+[Home](./index.md) > [@yext/analytics](./analytics.md) > [PagesAnalyticsConfig](./analytics.pagesanalyticsconfig.md) > [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
Signature:
```typescript
-path: string;
+pageUrl: string;
```
diff --git a/docs/analytics.pagesanalyticsservice.track.md b/docs/analytics.pagesanalyticsservice.track.md
index 3178b0f6..2ba01cc7 100644
--- a/docs/analytics.pagesanalyticsservice.track.md
+++ b/docs/analytics.pagesanalyticsservice.track.md
@@ -17,7 +17,7 @@ track(event: PagesAnalyticsEvent, conversionInfo?: ConversionDetails): PromiseReturns:
diff --git a/etc/analytics.api.md b/etc/analytics.api.md
index 1ec48228..7b26239c 100644
--- a/etc/analytics.api.md
+++ b/etc/analytics.api.md
@@ -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 {
}
@@ -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;
diff --git a/src/infra/ConversionTrackingReporter.ts b/src/infra/ConversionTrackingReporter.ts
index fef2e4e0..d6b284a9 100644
--- a/src/infra/ConversionTrackingReporter.ts
+++ b/src/infra/ConversionTrackingReporter.ts
@@ -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';
@@ -60,7 +60,7 @@ export class ConversionTrackingReporter implements ConversionTrackingService {
async trackListings(event: ListingsClickEvent): Promise {
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();
diff --git a/src/infra/PagesAnalyticsReporter.ts b/src/infra/PagesAnalyticsReporter.ts
index 405b4dca..18e82e41 100644
--- a/src/infra/PagesAnalyticsReporter.ts
+++ b/src/infra/PagesAnalyticsReporter.ts
@@ -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';
@@ -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}'`);
+ }
}
/**
@@ -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) {
@@ -119,6 +127,19 @@ export class PagesAnalyticsReporter implements PagesAnalyticsService{
/** {@inheritDoc PagesAnalyticsService.pageView} */
async pageView(): Promise {
+ 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);
}
diff --git a/src/models/config/PagesAnalyticsConfig.ts b/src/models/config/PagesAnalyticsConfig.ts
index 0eb5c2c1..59c37068 100644
--- a/src/models/config/PagesAnalyticsConfig.ts
+++ b/src/models/config/PagesAnalyticsConfig.ts
@@ -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
diff --git a/src/models/constants.ts b/src/models/constants.ts
index 4adabbf9..a3873511 100644
--- a/src/models/constants.ts
+++ b/src/models/constants.ts
@@ -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';
\ No newline at end of file
diff --git a/src/models/conversiontracking/CommonConversionData.ts b/src/models/conversiontracking/CommonConversionData.ts
index 82668353..df3849fc 100644
--- a/src/models/conversiontracking/CommonConversionData.ts
+++ b/src/models/conversiontracking/CommonConversionData.ts
@@ -1,5 +1,7 @@
/**
* Shared properties of both ConversionEvent and ListingsClickEvent
+ *
+ * @public
*/
export interface CommonConversionData {
/**
diff --git a/src/models/conversiontracking/ConversionDetails.ts b/src/models/conversiontracking/ConversionDetails.ts
index c44605e3..60973aef 100644
--- a/src/models/conversiontracking/ConversionDetails.ts
+++ b/src/models/conversiontracking/ConversionDetails.ts
@@ -1,5 +1,7 @@
/**
* The details of an individual conversion event, without the cookie id.
+ *
+ * @public
*/
export interface ConversionDetails {
/**
diff --git a/src/services/__mocks__/MockHttpRequesterService.ts b/src/services/__mocks__/MockHttpRequesterService.ts
index 841e3957..a3369052 100644
--- a/src/services/__mocks__/MockHttpRequesterService.ts
+++ b/src/services/__mocks__/MockHttpRequesterService.ts
@@ -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 {
diff --git a/test-site/src/index.ts b/test-site/src/index.ts
index e3711efc..9812b887 100644
--- a/test-site/src/index.ts
+++ b/test-site/src/index.ts
@@ -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,
diff --git a/tests/infra/ConversionTrackingReporter.ts b/tests/infra/ConversionTrackingReporter.ts
index 29f14386..0aa315a7 100644
--- a/tests/infra/ConversionTrackingReporter.ts
+++ b/tests/infra/ConversionTrackingReporter.ts
@@ -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',
);
});
@@ -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',
);
});
\ No newline at end of file
diff --git a/tests/infra/PagesAnalyticsReporter.ts b/tests/infra/PagesAnalyticsReporter.ts
index e7e8e48a..f76a7ef4 100644
--- a/tests/infra/PagesAnalyticsReporter.ts
+++ b/tests/infra/PagesAnalyticsReporter.ts
@@ -8,17 +8,18 @@ beforeEach(() => {
});
it('The static page page view URL is constructed correctly', () => {
+ const httpRequesterService = mockHttpRequesterService();
const reporter = new PagesAnalyticsReporter({
pageType: {
staticPageId: 'My Page Set',
name: 'static',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.pageView();
const expectedUrl = new URL('https://www.yext-pixel.com/store_pagespixel');
@@ -34,7 +35,7 @@ it('The static page page view URL is constructed correctly', () => {
expectedUrl.searchParams.set('pageurl', '/foo/bar');
expectedUrl.searchParams.set('pagesReferrer','https://www.google.com');
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('Should handle http errors properly', () => {
@@ -47,7 +48,7 @@ it('Should handle http errors properly', () => {
name: 'static',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
@@ -57,6 +58,7 @@ it('Should handle http errors properly', () => {
});
it('should track entity pages', () => {
+ const httpRequesterService = mockHttpRequesterService();
const expectedUrl = new URL('https://www.yext-pixel.com/store_pagespixel');
expectedUrl.searchParams.set('businessids', '0');
expectedUrl.searchParams.set('product', 'sites');
@@ -77,17 +79,18 @@ it('should track entity pages', () => {
id: 1,
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.pageView();
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('should track directory pages', () => {
+ const httpRequesterService = mockHttpRequesterService();
const reporter = new PagesAnalyticsReporter({
pageType: {
name: 'directory',
@@ -95,11 +98,11 @@ it('should track directory pages', () => {
id: 1,
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.pageView();
const expectedUrl = new URL('https://www.yext-pixel.com/store_pagespixel');
@@ -116,21 +119,22 @@ it('should track directory pages', () => {
expectedUrl.searchParams.set('pageurl', '/foo/bar');
expectedUrl.searchParams.set('pagesReferrer','https://www.google.com');
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('should track locator pages', () => {
+ const httpRequesterService = mockHttpRequesterService();
const reporter = new PagesAnalyticsReporter({
pageType: {
name: 'locator',
searchId: 'My Locator Page Set',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.pageView();
const expectedUrl = new URL('https://www.yext-pixel.com/store_pagespixel');
@@ -145,23 +149,23 @@ it('should track locator pages', () => {
expectedUrl.searchParams.set('pageurl', '/foo/bar');
expectedUrl.searchParams.set('pagesReferrer','https://www.google.com');
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('should track custom events', () => {
+ const httpRequesterService = mockHttpRequesterService();
const eventName = 'my_event_type_name';
-
const reporter = new PagesAnalyticsReporter({
pageType: {
name: 'static',
staticPageId: 'My Page Set',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.track({eventType: eventName});
const expectedUrl = new URL('https://www.yext-pixel.com/store_pagespixel');
@@ -177,21 +181,22 @@ it('should track custom events', () => {
expectedUrl.searchParams.set('pageurl', '/foo/bar');
expectedUrl.searchParams.set('pagesReferrer','https://www.google.com');
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('should use set the visitor', () => {
+ const httpRequesterService = mockHttpRequesterService();
const reporter = new PagesAnalyticsReporter({
pageType: {
name: 'static',
staticPageId: 'My Page Set',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.setVisitor({
id: 'foo',
@@ -215,21 +220,22 @@ it('should use set the visitor', () => {
expectedUrl.searchParams.set('visitorId', 'foo');
expectedUrl.searchParams.set('visitorIdMethod', 'bar');
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
});
it('should use conversion tracking endpoint and set cookie', () => {
+ const httpRequesterService = mockHttpRequesterService();
const reporter = new PagesAnalyticsReporter({
pageType: {
name: 'static',
staticPageId: 'My Page Set',
},
referrer: 'https://www.google.com',
- path: '/foo/bar',
+ pageUrl: 'https://www.foobar.com/foo/bar',
businessId: 0,
production: false,
siteId: 0
- }, mockHttpRequesterService);
+ }, httpRequesterService);
reporter.setVisitor({
id: 'foo',
@@ -255,6 +261,68 @@ it('should use conversion tracking endpoint and set cookie', () => {
expectedUrl.searchParams.set('visitorId', 'foo');
expectedUrl.searchParams.set('visitorIdMethod', 'bar');
- console.log(expectedUrl.toString());
- expect(mockHttpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+ expect(httpRequesterService.get).toHaveBeenLastCalledWith(expectedUrl.toString());
+});
+
+it('should throw an error if the pageUrl property is invalid', () => {
+ const httpRequesterService = mockHttpRequesterService();
+ expect.assertions(1);
+ const errMsg = 'pageUrl property must be a valid URL, was: \'foo/bar\'';
+ const thisShouldThrow = () => {
+ new PagesAnalyticsReporter({
+ pageType: {
+ staticPageId: 'My Page Set',
+ name: 'static',
+ },
+ referrer: 'https://www.google.com',
+ pageUrl: 'foo/bar',
+ businessId: 0,
+ production: false,
+ siteId: 0
+ }, httpRequesterService);
+ };
+
+ expect(thisShouldThrow).toThrow(errMsg);
+});
+
+it('should track listings with a pageview', async () => {
+ const httpRequesterService = mockHttpRequesterService();
+
+ const reporter = new PagesAnalyticsReporter({
+ pageType: {
+ name: 'static',
+ staticPageId: 'My Page Set',
+ },
+ referrer: 'https://www.google.com',
+ pageUrl: 'https://www.foobar.com/foo/bar?y_source=123455',
+ businessId: 0,
+ production: false,
+ siteId: 0
+ }, httpRequesterService);
+
+ reporter.setConversionTrackingEnabled(true, '123456');
+ await reporter.pageView();
+
+ const listingsUrl = new URL('https://realtimeanalytics.yext.com/listings');
+ listingsUrl.searchParams.set('y_source', '123455');
+ listingsUrl.searchParams.set('location', 'https://www.foobar.com/foo/bar?y_source=123455');
+ listingsUrl.searchParams.set('_yfpc', '123456');
+ listingsUrl.searchParams.set('v', '1001');
+
+ expect(httpRequesterService.get).toHaveBeenNthCalledWith(1, listingsUrl.toString());
+
+ const pageViewUrl = new URL('https://realtimeanalytics.yext.com/store_pagespixel');
+ pageViewUrl.searchParams.set('businessids', '0');
+ pageViewUrl.searchParams.set('product', 'sites');
+ pageViewUrl.searchParams.set('siteId', '0');
+ pageViewUrl.searchParams.set('isStaging', 'true');
+ pageViewUrl.searchParams.set('eventType', 'pageview');
+ pageViewUrl.searchParams.set('pageType', 'static');
+ pageViewUrl.searchParams.set('staticPageId', 'My Page Set');
+ pageViewUrl.searchParams.set('v', '1001');
+ pageViewUrl.searchParams.set('pageurl', '/foo/bar');
+ pageViewUrl.searchParams.set('pagesReferrer','https://www.google.com');
+
+ pageViewUrl.searchParams.set('_yfpc', '123456');
+ expect(httpRequesterService.get).toHaveBeenNthCalledWith(2, pageViewUrl.toString());
});
\ No newline at end of file
diff --git a/tests/infra/SearchAnalyticsReporter.ts b/tests/infra/SearchAnalyticsReporter.ts
index 42c43623..80b4a172 100644
--- a/tests/infra/SearchAnalyticsReporter.ts
+++ b/tests/infra/SearchAnalyticsReporter.ts
@@ -9,10 +9,11 @@ const config: SearchAnalyticsConfig = {
};
it('The URL is constructed correctly', () => {
- const analyticsReporter = new SearchAnalyticsReporter(config, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter(config, mockService);
analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1' });
const expectedUrl = `https://answers.yext-pixel.com/realtimeanalytics/data/answers/${config.businessId}`;
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expectedUrl, expect.anything());
+ expect(mockService.post).toHaveBeenLastCalledWith(expectedUrl, expect.anything());
});
it('The URL is constructed correctly with custom domains', () => {
@@ -20,14 +21,16 @@ it('The URL is constructed correctly with custom domains', () => {
...config,
domain: 'https://yext.com'
};
- const analyticsReporter = new SearchAnalyticsReporter(configWithCustomDomain, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter(configWithCustomDomain, mockService);
analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1'});
const expectedUrl = `https://yext.com/realtimeanalytics/data/answers/${config.businessId}`;
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expectedUrl, expect.anything());
+ expect(mockService.post).toHaveBeenLastCalledWith(expectedUrl, expect.anything());
});
it('The data is structured properly', () => {
- const analyticsReporter = new SearchAnalyticsReporter(config, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter(config, mockService);
analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1'});
const expectedData = {
data: {
@@ -38,11 +41,12 @@ it('The data is structured properly', () => {
queryId: '1'
}
};
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expect.anything(), expectedData);
+ expect(mockService.post).toHaveBeenLastCalledWith(expect.anything(), expectedData);
});
it('Additional params are sent properly', () => {
- const analyticsReporter = new SearchAnalyticsReporter(config, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter(config, mockService);
const additionalRequestAttributes = {
ytag: 123
};
@@ -57,12 +61,13 @@ it('Additional params are sent properly', () => {
},
...additionalRequestAttributes
};
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expect.anything(), expectedData);
+ expect(mockService.post).toHaveBeenLastCalledWith(expect.anything(), expectedData);
});
it('Returns a resolved promise after a successful report', () => {
expect.assertions(1);
- const analyticsReporter = new SearchAnalyticsReporter(config, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter(config, mockService);
const resPromise = analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1' });
expect(resPromise).resolves.toEqual(undefined);
});
@@ -77,7 +82,8 @@ it('Performs a promise rejection when the API responds with an error', () => {
it('Visitor is set and passed properly', () => {
const visitorParam = { visitor: { id: '123'} };
- const analyticsReporter = new SearchAnalyticsReporter({...config, ...visitorParam}, mockHttpRequesterService);
+ const mockService = mockHttpRequesterService();
+ const analyticsReporter = new SearchAnalyticsReporter({...config, ...visitorParam}, mockService);
analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1' });
const data = {
businessId: 123,
@@ -92,10 +98,10 @@ it('Visitor is set and passed properly', () => {
...visitorParam
}
};
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expect.anything(),
+ expect(mockService.post).toHaveBeenLastCalledWith(expect.anything(),
expectedDataWithVisitor);
analyticsReporter.setVisitor(undefined);
analyticsReporter.report({ type: 'SCROLL_TO_BOTTOM_OF_PAGE', queryId: '1' });
- expect(mockHttpRequesterService.post).toHaveBeenLastCalledWith(expect.anything(), { data });
+ expect(mockService.post).toHaveBeenLastCalledWith(expect.anything(), { data });
});