diff --git a/packages/browser-destinations/destinations/fullstory/package.json b/packages/browser-destinations/destinations/fullstory/package.json
index c3b266e96f..ed2addbe94 100644
--- a/packages/browser-destinations/destinations/fullstory/package.json
+++ b/packages/browser-destinations/destinations/fullstory/package.json
@@ -15,7 +15,7 @@
},
"typings": "./dist/esm",
"dependencies": {
- "@fullstory/browser": "^1.4.9",
+ "@fullstory/browser": "^2.0.3",
"@segment/actions-core": "^3.97.0",
"@segment/browser-destination-runtime": "^1.27.0"
},
diff --git a/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstory.test.ts b/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstory.test.ts
index c3cf7dff89..861614e765 100644
--- a/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstory.test.ts
+++ b/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstory.test.ts
@@ -1,6 +1,12 @@
import { Analytics, Context } from '@segment/analytics-next'
-import fullstory, { destination } from '..'
+import fullstory from '..'
+import trackEvent from '../trackEvent'
+import identifyUser from '../identifyUser'
+import viewedPage from '../viewedPage'
import { Subscription } from '@segment/browser-destination-runtime/types'
+import { defaultValues } from '@segment/actions-core/*'
+
+const FakeOrgId = 'asdf-qwer'
const example: Subscription[] = [
{
@@ -8,82 +14,36 @@ const example: Subscription[] = [
name: 'Track Event',
enabled: true,
subscribe: 'type = "track"',
- mapping: {
- name: {
- '@path': '$.name'
- },
- properties: {
- '@path': '$.properties'
- }
- }
+ mapping: defaultValues(trackEvent.fields)
},
{
partnerAction: 'identifyUser',
name: 'Identify User',
enabled: true,
subscribe: 'type = "identify"',
- mapping: {
- anonymousId: {
- '@path': '$.anonymousId'
- },
- userId: {
- '@path': '$.userId'
- },
- email: {
- '@path': '$.traits.email'
- },
- traits: {
- '@path': '$.traits'
- },
- displayName: {
- '@path': '$.traits.name'
- }
- }
+ mapping: defaultValues(identifyUser.fields)
+ },
+ {
+ partnerAction: 'viewedPage',
+ name: 'Viewed Page',
+ enabled: true,
+ subscribe: 'type = "page"',
+ mapping: defaultValues(viewedPage.fields)
}
]
-test('can load fullstory', async () => {
- const [event] = await fullstory({
- orgId: 'thefullstory.com',
- subscriptions: example
- })
-
- jest.spyOn(destination.actions.trackEvent, 'perform')
- jest.spyOn(destination, 'initialize')
-
- await event.load(Context.system(), {} as Analytics)
- expect(destination.initialize).toHaveBeenCalled()
-
- const ctx = await event.track?.(
- new Context({
- type: 'track',
- properties: {
- banana: '📞'
- }
- })
- )
-
- expect(destination.actions.trackEvent.perform).toHaveBeenCalled()
- expect(ctx).not.toBeUndefined()
-
- const scripts = window.document.querySelectorAll('script')
- expect(scripts).toMatchInlineSnapshot(`
- NodeList [
- ,
- ,
- ]
- `)
+beforeEach(() => {
+ delete window._fs_initialized
+ if (window._fs_namespace) {
+ delete window[window._fs_namespace]
+ delete window._fs_namespace
+ }
})
describe('#track', () => {
it('sends record events to fullstory on "event"', async () => {
const [event] = await fullstory({
- orgId: 'thefullstory.com',
+ orgId: FakeOrgId,
subscriptions: example
})
@@ -93,7 +53,7 @@ describe('#track', () => {
await event.track?.(
new Context({
type: 'track',
- name: 'hello!',
+ event: 'hello!',
properties: {
banana: '📞'
}
@@ -112,16 +72,16 @@ describe('#track', () => {
describe('#identify', () => {
it('should default to anonymousId', async () => {
- const [_, identifyUser] = await fullstory({
- orgId: 'thefullstory.com',
+ const [_, identify] = await fullstory({
+ orgId: FakeOrgId,
subscriptions: example
})
- await identifyUser.load(Context.system(), {} as Analytics)
+ await identify.load(Context.system(), {} as Analytics)
const fs = jest.spyOn(window.FS, 'setUserVars')
const fsId = jest.spyOn(window.FS, 'identify')
- await identifyUser.identify?.(
+ await identify.identify?.(
new Context({
type: 'identify',
anonymousId: 'anon',
@@ -137,7 +97,7 @@ describe('#identify', () => {
}),
it('should send an id', async () => {
const [_, identifyUser] = await fullstory({
- orgId: 'thefullstory.com',
+ orgId: FakeOrgId,
subscriptions: example
})
await identifyUser.load(Context.system(), {} as Analytics)
@@ -147,14 +107,14 @@ describe('#identify', () => {
expect(fsId).toHaveBeenCalledWith('id', {}, 'segment-browser-actions')
}),
it('should camelCase custom traits', async () => {
- const [_, identifyUser] = await fullstory({
- orgId: 'thefullstory.com',
+ const [_, identify] = await fullstory({
+ orgId: FakeOrgId,
subscriptions: example
})
- await identifyUser.load(Context.system(), {} as Analytics)
+ await identify.load(Context.system(), {} as Analytics)
const fsId = jest.spyOn(window.FS, 'identify')
- await identifyUser.identify?.(
+ await identify.identify?.(
new Context({
type: 'identify',
userId: 'id',
@@ -173,15 +133,15 @@ describe('#identify', () => {
})
it('can set user vars', async () => {
- const [_, identifyUser] = await fullstory({
- orgId: 'thefullstory.com',
+ const [_, identify] = await fullstory({
+ orgId: FakeOrgId,
subscriptions: example
})
- await identifyUser.load(Context.system(), {} as Analytics)
+ await identify.load(Context.system(), {} as Analytics)
const fs = jest.spyOn(window.FS, 'setUserVars')
- await identifyUser.identify?.(
+ await identify.identify?.(
new Context({
type: 'identify',
traits: {
@@ -204,15 +164,15 @@ describe('#identify', () => {
})
it('should set displayName correctly', async () => {
- const [_, identifyUser] = await fullstory({
- orgId: 'thefullstory.com',
+ const [_, identify] = await fullstory({
+ orgId: FakeOrgId,
subscriptions: example
})
- await identifyUser.load(Context.system(), {} as Analytics)
+ await identify.load(Context.system(), {} as Analytics)
const fs = jest.spyOn(window.FS, 'identify')
- await identifyUser.identify?.(
+ await identify.identify?.(
new Context({
type: 'identify',
userId: 'userId',
@@ -236,3 +196,93 @@ describe('#identify', () => {
)
})
})
+
+describe('#page', () => {
+ it('sends page events to fullstory on "page" (category edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+ const fs = jest.spyOn(window.FS, 'setVars')
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ category: 'Walruses',
+ name: 'Walrus Page',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(fs).toHaveBeenCalledWith(
+ 'page',
+ {
+ pageName: 'Walruses',
+ banana: '📞'
+ },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('sends page events to fullstory on "page" (name edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+ const fs = jest.spyOn(window.FS, 'setVars')
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ name: 'Walrus Page',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(fs).toHaveBeenCalledWith(
+ 'page',
+ {
+ pageName: 'Walrus Page',
+ banana: '📞'
+ },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('sends page events to fullstory on "page" (no pageName edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+ const fs = jest.spyOn(window.FS, 'setVars')
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ properties: {
+ banana: '📞',
+ keys: '🗝🔑'
+ }
+ })
+ )
+
+ expect(fs).toHaveBeenCalledWith(
+ 'page',
+ {
+ banana: '📞',
+ keys: '🗝🔑'
+ },
+ 'segment-browser-actions'
+ )
+ })
+})
diff --git a/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstoryV2.test.ts b/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstoryV2.test.ts
new file mode 100644
index 0000000000..2399ce96c4
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/__tests__/fullstoryV2.test.ts
@@ -0,0 +1,277 @@
+import { Analytics, Context } from '@segment/analytics-next'
+import fullstory from '..'
+import trackEventV2 from '../trackEventV2'
+import identifyUserV2 from '../identifyUserV2'
+import viewedPageV2 from '../viewedPageV2'
+import { FS as FSApi } from '../types'
+import { Subscription } from '@segment/browser-destination-runtime/types'
+import { defaultValues } from '@segment/actions-core/*'
+
+jest.mock('@fullstory/browser', () => ({
+ ...jest.requireActual('@fullstory/browser'),
+ init: () => {
+ window.FS = jest.fn() as unknown as FSApi
+ }
+}))
+
+const FakeOrgId = 'asdf-qwer'
+
+const example: Subscription[] = [
+ {
+ partnerAction: 'trackEventV2',
+ name: 'Track Event',
+ enabled: true,
+ subscribe: 'type = "track"',
+ mapping: defaultValues(trackEventV2.fields)
+ },
+ {
+ partnerAction: 'identifyUserV2',
+ name: 'Identify User',
+ enabled: true,
+ subscribe: 'type = "identify"',
+ mapping: defaultValues(identifyUserV2.fields)
+ },
+ {
+ partnerAction: 'viewedPageV2',
+ name: 'Viewed Page',
+ enabled: true,
+ subscribe: 'type = "page"',
+ mapping: defaultValues(viewedPageV2.fields)
+ }
+]
+
+describe('#track', () => {
+ it('sends record events to fullstory on "event"', async () => {
+ const [event] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await event.load(Context.system(), {} as Analytics)
+
+ await event.track?.(
+ new Context({
+ type: 'track',
+ event: 'hello!',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'trackEvent',
+ {
+ name: 'hello!',
+ properties: {
+ banana: '📞'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+})
+
+describe('#identify', () => {
+ it('should default to anonymousId', async () => {
+ const [_, identifyUser] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await identifyUser.load(Context.system(), {} as Analytics)
+
+ await identifyUser.identify?.(
+ new Context({
+ type: 'identify',
+ anonymousId: 'anon',
+ traits: {
+ testProp: false
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledTimes(1)
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setProperties',
+ { type: 'user', properties: { segmentAnonymousId: 'anon', testProp: false } },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('should send an id', async () => {
+ const [_, identifyUser] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+ await identifyUser.load(Context.system(), {} as Analytics)
+
+ await identifyUser.identify?.(new Context({ type: 'identify', userId: 'id' }))
+ expect(window.FS).toHaveBeenCalledWith('setIdentity', { uid: 'id', properties: {} }, 'segment-browser-actions')
+ })
+
+ it('can set user vars', async () => {
+ const [_, identifyUser] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await identifyUser.load(Context.system(), {} as Analytics)
+
+ await identifyUser.identify?.(
+ new Context({
+ type: 'identify',
+ traits: {
+ name: 'Hasbulla',
+ email: 'thegoat@world',
+ height: '50cm'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setProperties',
+ {
+ type: 'user',
+ properties: {
+ displayName: 'Hasbulla',
+ email: 'thegoat@world',
+ height: '50cm',
+ name: 'Hasbulla'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('should set displayName correctly', async () => {
+ const [_, identifyUser] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await identifyUser.load(Context.system(), {} as Analytics)
+
+ await identifyUser.identify?.(
+ new Context({
+ type: 'identify',
+ userId: 'userId',
+ traits: {
+ name: 'Hasbulla',
+ email: 'thegoat@world',
+ height: '50cm'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setIdentity',
+ {
+ uid: 'userId',
+ properties: {
+ displayName: 'Hasbulla',
+ email: 'thegoat@world',
+ height: '50cm',
+ name: 'Hasbulla'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+})
+
+describe('#page', () => {
+ it('sends page events to fullstory on "page" (category edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ category: 'Walruses',
+ name: 'Walrus Page',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setProperties',
+ {
+ type: 'page',
+ properties: {
+ pageName: 'Walruses',
+ banana: '📞'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('sends page events to fullstory on "page" (name edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ name: 'Walrus Page',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setProperties',
+ {
+ type: 'page',
+ properties: {
+ pageName: 'Walrus Page',
+ banana: '📞'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+
+ it('sends page events to fullstory on "page" (no pageName edition)', async () => {
+ const [, , viewed] = await fullstory({
+ orgId: FakeOrgId,
+ subscriptions: example
+ })
+
+ await viewed.load(Context.system(), {} as Analytics)
+
+ await viewed.page?.(
+ new Context({
+ type: 'page',
+ properties: {
+ banana: '📞',
+ keys: '🗝🔑'
+ }
+ })
+ )
+
+ expect(window.FS).toHaveBeenCalledWith(
+ 'setProperties',
+ {
+ type: 'page',
+ properties: {
+ banana: '📞',
+ keys: '🗝🔑'
+ }
+ },
+ 'segment-browser-actions'
+ )
+ })
+})
diff --git a/packages/browser-destinations/destinations/fullstory/src/__tests__/initialization.test.ts b/packages/browser-destinations/destinations/fullstory/src/__tests__/initialization.test.ts
new file mode 100644
index 0000000000..9f0274bc96
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/__tests__/initialization.test.ts
@@ -0,0 +1,81 @@
+import { Analytics, Context } from '@segment/analytics-next'
+import fullstory, { destination } from '..'
+import { Subscription } from '@segment/browser-destination-runtime/types'
+
+const example: Subscription[] = [
+ {
+ partnerAction: 'trackEvent',
+ name: 'Track Event',
+ enabled: true,
+ subscribe: 'type = "track"',
+ mapping: {
+ name: {
+ '@path': '$.name'
+ },
+ properties: {
+ '@path': '$.properties'
+ }
+ }
+ },
+ {
+ partnerAction: 'identifyUser',
+ name: 'Identify User',
+ enabled: true,
+ subscribe: 'type = "identify"',
+ mapping: {
+ anonymousId: {
+ '@path': '$.anonymousId'
+ },
+ userId: {
+ '@path': '$.userId'
+ },
+ email: {
+ '@path': '$.traits.email'
+ },
+ traits: {
+ '@path': '$.traits'
+ },
+ displayName: {
+ '@path': '$.traits.name'
+ }
+ }
+ }
+]
+
+test('can load fullstory', async () => {
+ const [event] = await fullstory({
+ orgId: 'thefullstory.com',
+ subscriptions: example
+ })
+
+ jest.spyOn(destination.actions.trackEvent, 'perform')
+ jest.spyOn(destination, 'initialize')
+
+ await event.load(Context.system(), {} as Analytics)
+ expect(destination.initialize).toHaveBeenCalled()
+
+ const ctx = await event.track?.(
+ new Context({
+ type: 'track',
+ properties: {
+ banana: '📞'
+ }
+ })
+ )
+
+ expect(destination.actions.trackEvent.perform).toHaveBeenCalled()
+ expect(ctx).not.toBeUndefined()
+
+ const scripts = window.document.querySelectorAll('script')
+ expect(scripts).toMatchInlineSnapshot(`
+ NodeList [
+ ,
+ ,
+ ]
+ `)
+})
diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts
new file mode 100644
index 0000000000..e325fbc445
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/generated-types.ts
@@ -0,0 +1,26 @@
+// Generated file. DO NOT MODIFY IT BY HAND.
+
+export interface Payload {
+ /**
+ * The user's id
+ */
+ userId?: string
+ /**
+ * The user's anonymous id
+ */
+ anonymousId?: string
+ /**
+ * The user's display name
+ */
+ displayName?: string
+ /**
+ * The user's email
+ */
+ email?: string
+ /**
+ * The Segment traits to be forwarded to FullStory
+ */
+ traits?: {
+ [k: string]: unknown
+ }
+}
diff --git a/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts
new file mode 100644
index 0000000000..97e7db1e7f
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/identifyUserV2/index.ts
@@ -0,0 +1,95 @@
+import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
+import type { Settings } from '../generated-types'
+import type { Payload } from './generated-types'
+import type { FS } from '../types'
+import { segmentEventSource } from '..'
+
+// Change from unknown to the partner SDK types
+const action: BrowserActionDefinition = {
+ title: 'Identify User V2',
+ description: 'Sets user identity properties',
+ platform: 'web',
+ defaultSubscription: 'type = "identify"',
+ fields: {
+ userId: {
+ type: 'string',
+ required: false,
+ description: "The user's id",
+ label: 'User ID',
+ default: {
+ '@path': '$.userId'
+ }
+ },
+ anonymousId: {
+ type: 'string',
+ required: false,
+ description: "The user's anonymous id",
+ label: 'Anonymous ID',
+ default: {
+ '@path': '$.anonymousId'
+ }
+ },
+ displayName: {
+ type: 'string',
+ required: false,
+ description: "The user's display name",
+ label: 'Display Name',
+ default: {
+ '@path': '$.traits.name'
+ }
+ },
+ email: {
+ type: 'string',
+ required: false,
+ description: "The user's email",
+ label: 'Email',
+ default: {
+ '@path': '$.traits.email'
+ }
+ },
+ traits: {
+ type: 'object',
+ required: false,
+ description: 'The Segment traits to be forwarded to FullStory',
+ label: 'Traits',
+ default: {
+ '@path': '$.traits'
+ }
+ }
+ },
+ perform: (FS, event) => {
+ const newTraits: Record = event.payload.traits || {}
+
+ if (event.payload.anonymousId) {
+ newTraits.segmentAnonymousId = event.payload.anonymousId
+ }
+
+ const userProperties = {
+ ...newTraits,
+ ...(event.payload.email !== undefined && { email: event.payload.email }),
+ ...(event.payload.displayName !== undefined && { displayName: event.payload.displayName })
+ }
+
+ if (event.payload.userId) {
+ FS(
+ 'setIdentity',
+ {
+ uid: event.payload.userId,
+ properties: userProperties
+ },
+ segmentEventSource
+ )
+ } else {
+ FS(
+ 'setProperties',
+ {
+ type: 'user',
+ properties: userProperties
+ },
+ segmentEventSource
+ )
+ }
+ }
+}
+
+export default action
diff --git a/packages/browser-destinations/destinations/fullstory/src/index.ts b/packages/browser-destinations/destinations/fullstory/src/index.ts
index c7494cabe4..01b1ac4d75 100644
--- a/packages/browser-destinations/destinations/fullstory/src/index.ts
+++ b/packages/browser-destinations/destinations/fullstory/src/index.ts
@@ -1,11 +1,14 @@
import type { FS } from './types'
import type { BrowserDestinationDefinition } from '@segment/browser-destination-runtime/types'
-import { FSPackage } from './types'
+import { initFullStory } from './types'
import { browserDestination } from '@segment/browser-destination-runtime/shim'
import type { Settings } from './generated-types'
import trackEvent from './trackEvent'
+import trackEventV2 from './trackEventV2'
import identifyUser from './identifyUser'
+import identifyUserV2 from './identifyUserV2'
import viewedPage from './viewedPage'
+import viewedPageV2 from './viewedPageV2'
import { defaultValues } from '@segment/actions-core'
declare global {
@@ -24,15 +27,22 @@ export const destination: BrowserDestinationDefinition = {
{
name: 'Track Event',
subscribe: 'type = "track"',
- partnerAction: 'trackEvent',
- mapping: defaultValues(trackEvent.fields),
+ partnerAction: 'trackEventV2',
+ mapping: defaultValues(trackEventV2.fields),
type: 'automatic'
},
{
name: 'Identify User',
subscribe: 'type = "identify"',
- partnerAction: 'identifyUser',
- mapping: defaultValues(identifyUser.fields),
+ partnerAction: 'identifyUserV2',
+ mapping: defaultValues(identifyUserV2.fields),
+ type: 'automatic'
+ },
+ {
+ name: 'Viewed Page',
+ subscribe: 'type = "page"',
+ partnerAction: 'viewedPageV2',
+ mapping: defaultValues(viewedPageV2.fields),
type: 'automatic'
}
],
@@ -60,11 +70,14 @@ export const destination: BrowserDestinationDefinition = {
},
actions: {
trackEvent,
+ trackEventV2,
identifyUser,
- viewedPage
+ identifyUserV2,
+ viewedPage,
+ viewedPageV2
},
initialize: async ({ settings }, dependencies) => {
- FSPackage.init(settings)
+ initFullStory(settings)
await dependencies.resolveWhen(() => Object.prototype.hasOwnProperty.call(window, 'FS'), 100)
return window.FS
}
diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts
new file mode 100644
index 0000000000..6ec21ec140
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/generated-types.ts
@@ -0,0 +1,14 @@
+// Generated file. DO NOT MODIFY IT BY HAND.
+
+export interface Payload {
+ /**
+ * The name of the event.
+ */
+ name: string
+ /**
+ * A JSON object containing additional information about the event that will be indexed by FullStory.
+ */
+ properties?: {
+ [k: string]: unknown
+ }
+}
diff --git a/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts
new file mode 100644
index 0000000000..50f2f7b2c0
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/trackEventV2/index.ts
@@ -0,0 +1,44 @@
+import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
+import type { Settings } from '../generated-types'
+import type { Payload } from './generated-types'
+import type { FS } from '../types'
+import { segmentEventSource } from '..'
+
+const action: BrowserActionDefinition = {
+ title: 'Track Event V2',
+ description: 'Track events',
+ platform: 'web',
+ defaultSubscription: 'type = "track"',
+ fields: {
+ name: {
+ description: 'The name of the event.',
+ label: 'Name',
+ required: true,
+ type: 'string',
+ default: {
+ '@path': '$.event'
+ }
+ },
+ properties: {
+ description: 'A JSON object containing additional information about the event that will be indexed by FullStory.',
+ label: 'Properties',
+ required: false,
+ type: 'object',
+ default: {
+ '@path': '$.properties'
+ }
+ }
+ },
+ perform: (FS, event) => {
+ FS(
+ 'trackEvent',
+ {
+ name: event.payload.name,
+ properties: event.payload.properties ?? {}
+ },
+ segmentEventSource
+ )
+ }
+}
+
+export default action
diff --git a/packages/browser-destinations/destinations/fullstory/src/types.ts b/packages/browser-destinations/destinations/fullstory/src/types.ts
index fa6f59e129..7a23e1a0e5 100644
--- a/packages/browser-destinations/destinations/fullstory/src/types.ts
+++ b/packages/browser-destinations/destinations/fullstory/src/types.ts
@@ -1,10 +1,4 @@
-import * as FullStory from '@fullstory/browser'
+import { FullStory, init as initFullStory } from '@fullstory/browser'
-export const FSPackage = FullStory
-export type FS = typeof FullStory & {
- // setVars is not available on the FS client yet.
- setVars: (eventName: string, eventProperties: object, source: string) => {}
- setUserVars: (eventProperties: object, source: string) => void
- event: (eventName: string, eventProperties: { [key: string]: unknown }, source: string) => void
- identify: (uid: string, customVars: FullStory.UserVars, source: string) => void
-}
+export type FS = typeof FullStory
+export { FullStory, initFullStory }
diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts
new file mode 100644
index 0000000000..fa90a6ee12
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/generated-types.ts
@@ -0,0 +1,14 @@
+// Generated file. DO NOT MODIFY IT BY HAND.
+
+export interface Payload {
+ /**
+ * The name of the page that was viewed.
+ */
+ pageName?: string
+ /**
+ * The properties of the page that was viewed.
+ */
+ properties?: {
+ [k: string]: unknown
+ }
+}
diff --git a/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts
new file mode 100644
index 0000000000..a531c0df22
--- /dev/null
+++ b/packages/browser-destinations/destinations/fullstory/src/viewedPageV2/index.ts
@@ -0,0 +1,52 @@
+import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
+import type { Settings } from '../generated-types'
+import type { Payload } from './generated-types'
+import type { FS } from '../types'
+import { segmentEventSource } from '..'
+
+const action: BrowserActionDefinition = {
+ title: 'Viewed Page V2',
+ description: 'Sets page properties',
+ defaultSubscription: 'type = "page"',
+ platform: 'web',
+ fields: {
+ pageName: {
+ type: 'string',
+ required: false,
+ description: 'The name of the page that was viewed.',
+ label: 'Page Name',
+ default: {
+ '@if': {
+ exists: { '@path': '$.category' },
+ then: { '@path': '$.category' },
+ else: { '@path': '$.name' }
+ }
+ }
+ },
+ properties: {
+ type: 'object',
+ required: false,
+ description: 'The properties of the page that was viewed.',
+ label: 'Properties',
+ default: {
+ '@path': '$.properties'
+ }
+ }
+ },
+ perform: (FS, event) => {
+ const properties: object = event.payload.pageName
+ ? { pageName: event.payload.pageName, ...event.payload.properties }
+ : { ...event.payload.properties }
+
+ FS(
+ 'setProperties',
+ {
+ type: 'page',
+ properties
+ },
+ segmentEventSource
+ )
+ }
+}
+
+export default action
diff --git a/yarn.lock b/yarn.lock
index e892fc43f7..b9cc34ba4b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1256,17 +1256,17 @@
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.1.6.tgz#22958c042e10b67463997bd6ea7115fe28cbcaf9"
integrity sha512-OfX7E2oUDYxtBvsuS4e/jSn4Q9Qb6DzgeYtsAdkPZ47znpoNsMgZw0+tVijiv3uGNR6dgNlty6r9rzIzHjtd/A==
-"@fullstory/browser@^1.4.9":
- version "1.7.1"
- resolved "https://registry.yarnpkg.com/@fullstory/browser/-/browser-1.7.1.tgz#eb94fcb5e21b13a1b30de58951480ac344e61cdd"
- integrity sha512-IBPisG+xRyTHHX8XkZJkQRbP2hVYNMZUYW8R3YiB582dl/VZImkFN+LopIAfPqB97FAZgUTofi7flkrHT4Qmtg==
+"@fullstory/browser@^2.0.3":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@fullstory/browser/-/browser-2.0.3.tgz#09c0b590d81a8098f8fd85d160a44e4f73e15bfb"
+ integrity sha512-usjH8FB1O2LiSWoblsuKhFhlYDGpIPuyQVOx4JXtxm9QmQARdKZdNq1vPijxuDvOGjhwtVZa4JmhvByRRuDPnQ==
dependencies:
- "@fullstory/snippet" "1.3.1"
+ "@fullstory/snippet" "2.0.3"
-"@fullstory/snippet@1.3.1":
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/@fullstory/snippet/-/snippet-1.3.1.tgz#6817ea94601e071e630b25262e703ca356a5f537"
- integrity sha512-NgrBWGHH5i8zejlRFSyJNhovkNqHAXsWKrcXIWaABrgESwbkdGETjOU7BD7d1ZeT0X+QXL/2yr/1y4xnWfVkwQ==
+"@fullstory/snippet@2.0.3":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@fullstory/snippet/-/snippet-2.0.3.tgz#d5410132becc3d0115bb129b57461d228c73b5f0"
+ integrity sha512-EaCuTQSLv5FvnjHLbTxErn3sS1+nLqf1p6sA/c4PV49stBtkUakA0eLhJJdaw0WLdXyEzZXf86lRNsjEzrgGPw==
"@gar/promisify@^1.1.3":
version "1.1.3"