@segment/analytics-browser-mixpanel-web-actions 1.0.1-staging-294d81392.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +31 -0
  2. package/dist/cjs/alias/generated-types.d.ts +4 -0
  3. package/dist/cjs/alias/generated-types.js +3 -0
  4. package/dist/cjs/alias/generated-types.js.map +1 -0
  5. package/dist/cjs/alias/index.d.ts +6 -0
  6. package/dist/cjs/alias/index.js +32 -0
  7. package/dist/cjs/alias/index.js.map +1 -0
  8. package/dist/cjs/constants.d.ts +14 -0
  9. package/dist/cjs/constants.js +18 -0
  10. package/dist/cjs/constants.js.map +1 -0
  11. package/dist/cjs/fields.d.ts +11 -0
  12. package/dist/cjs/fields.js +162 -0
  13. package/dist/cjs/fields.js.map +1 -0
  14. package/dist/cjs/functions.d.ts +7 -0
  15. package/dist/cjs/functions.js +39 -0
  16. package/dist/cjs/functions.js.map +1 -0
  17. package/dist/cjs/generated-types.d.ts +30 -0
  18. package/dist/cjs/generated-types.js +3 -0
  19. package/dist/cjs/generated-types.js.map +1 -0
  20. package/dist/cjs/group/generated-types.d.ts +16 -0
  21. package/dist/cjs/group/generated-types.js +3 -0
  22. package/dist/cjs/group/generated-types.js.map +1 -0
  23. package/dist/cjs/group/index.d.ts +6 -0
  24. package/dist/cjs/group/index.js +21 -0
  25. package/dist/cjs/group/index.js.map +1 -0
  26. package/dist/cjs/identify/generated-types.d.ts +19 -0
  27. package/dist/cjs/identify/generated-types.js +3 -0
  28. package/dist/cjs/identify/generated-types.js.map +1 -0
  29. package/dist/cjs/identify/index.d.ts +6 -0
  30. package/dist/cjs/identify/index.js +21 -0
  31. package/dist/cjs/identify/index.js.map +1 -0
  32. package/dist/cjs/index.d.ts +11 -0
  33. package/dist/cjs/index.js +76 -0
  34. package/dist/cjs/index.js.map +1 -0
  35. package/dist/cjs/init-script.d.ts +1 -0
  36. package/dist/cjs/init-script.js +65 -0
  37. package/dist/cjs/init-script.js.map +1 -0
  38. package/dist/cjs/setting-fields.d.ts +2 -0
  39. package/dist/cjs/setting-fields.js +273 -0
  40. package/dist/cjs/setting-fields.js.map +1 -0
  41. package/dist/cjs/track/generated-types.d.ts +37 -0
  42. package/dist/cjs/track/generated-types.js +3 -0
  43. package/dist/cjs/track/generated-types.js.map +1 -0
  44. package/dist/cjs/track/index.d.ts +6 -0
  45. package/dist/cjs/track/index.js +93 -0
  46. package/dist/cjs/track/index.js.map +1 -0
  47. package/dist/cjs/trackPageView/generated-types.d.ts +37 -0
  48. package/dist/cjs/trackPageView/generated-types.js +3 -0
  49. package/dist/cjs/trackPageView/generated-types.js.map +1 -0
  50. package/dist/cjs/trackPageView/index.d.ts +6 -0
  51. package/dist/cjs/trackPageView/index.js +101 -0
  52. package/dist/cjs/trackPageView/index.js.map +1 -0
  53. package/dist/cjs/types.d.ts +68 -0
  54. package/dist/cjs/types.js +3 -0
  55. package/dist/cjs/types.js.map +1 -0
  56. package/dist/esm/alias/generated-types.d.ts +4 -0
  57. package/dist/esm/alias/generated-types.js +2 -0
  58. package/dist/esm/alias/generated-types.js.map +1 -0
  59. package/dist/esm/alias/index.d.ts +6 -0
  60. package/dist/esm/alias/index.js +30 -0
  61. package/dist/esm/alias/index.js.map +1 -0
  62. package/dist/esm/constants.d.ts +14 -0
  63. package/dist/esm/constants.js +15 -0
  64. package/dist/esm/constants.js.map +1 -0
  65. package/dist/esm/fields.d.ts +11 -0
  66. package/dist/esm/fields.js +159 -0
  67. package/dist/esm/fields.js.map +1 -0
  68. package/dist/esm/functions.d.ts +7 -0
  69. package/dist/esm/functions.js +35 -0
  70. package/dist/esm/functions.js.map +1 -0
  71. package/dist/esm/generated-types.d.ts +30 -0
  72. package/dist/esm/generated-types.js +2 -0
  73. package/dist/esm/generated-types.js.map +1 -0
  74. package/dist/esm/group/generated-types.d.ts +16 -0
  75. package/dist/esm/group/generated-types.js +2 -0
  76. package/dist/esm/group/generated-types.js.map +1 -0
  77. package/dist/esm/group/index.d.ts +6 -0
  78. package/dist/esm/group/index.js +19 -0
  79. package/dist/esm/group/index.js.map +1 -0
  80. package/dist/esm/identify/generated-types.d.ts +19 -0
  81. package/dist/esm/identify/generated-types.js +2 -0
  82. package/dist/esm/identify/generated-types.js.map +1 -0
  83. package/dist/esm/identify/index.d.ts +6 -0
  84. package/dist/esm/identify/index.js +19 -0
  85. package/dist/esm/identify/index.js.map +1 -0
  86. package/dist/esm/index.d.ts +11 -0
  87. package/dist/esm/index.js +72 -0
  88. package/dist/esm/index.js.map +1 -0
  89. package/dist/esm/init-script.d.ts +1 -0
  90. package/dist/esm/init-script.js +62 -0
  91. package/dist/esm/init-script.js.map +1 -0
  92. package/dist/esm/setting-fields.d.ts +2 -0
  93. package/dist/esm/setting-fields.js +270 -0
  94. package/dist/esm/setting-fields.js.map +1 -0
  95. package/dist/esm/track/generated-types.d.ts +37 -0
  96. package/dist/esm/track/generated-types.js +2 -0
  97. package/dist/esm/track/generated-types.js.map +1 -0
  98. package/dist/esm/track/index.d.ts +6 -0
  99. package/dist/esm/track/index.js +91 -0
  100. package/dist/esm/track/index.js.map +1 -0
  101. package/dist/esm/trackPageView/generated-types.d.ts +37 -0
  102. package/dist/esm/trackPageView/generated-types.js +2 -0
  103. package/dist/esm/trackPageView/generated-types.js.map +1 -0
  104. package/dist/esm/trackPageView/index.d.ts +6 -0
  105. package/dist/esm/trackPageView/index.js +99 -0
  106. package/dist/esm/trackPageView/index.js.map +1 -0
  107. package/dist/esm/types.d.ts +68 -0
  108. package/dist/esm/types.js +2 -0
  109. package/dist/esm/types.js.map +1 -0
  110. package/dist/tsconfig.tsbuildinfo +1 -0
  111. package/package.json +25 -0
  112. package/src/alias/__tests__/index.test.ts +95 -0
  113. package/src/alias/generated-types.ts +12 -0
  114. package/src/alias/index.ts +35 -0
  115. package/src/constants.ts +16 -0
  116. package/src/fields.ts +173 -0
  117. package/src/functions.ts +57 -0
  118. package/src/generated-types.ts +116 -0
  119. package/src/group/__tests__/index.test.ts +126 -0
  120. package/src/group/generated-types.ts +42 -0
  121. package/src/group/index.ts +29 -0
  122. package/src/identify/__tests__/index.test.ts +135 -0
  123. package/src/identify/generated-types.ts +54 -0
  124. package/src/identify/index.ts +29 -0
  125. package/src/index.ts +99 -0
  126. package/src/init-script.ts +63 -0
  127. package/src/setting-fields.ts +273 -0
  128. package/src/track/__tests__/index.test.ts +196 -0
  129. package/src/track/generated-types.ts +102 -0
  130. package/src/track/index.ts +109 -0
  131. package/src/trackPageView/__tests__/index.test.ts +250 -0
  132. package/src/trackPageView/generated-types.ts +102 -0
  133. package/src/trackPageView/index.ts +116 -0
  134. package/src/types.ts +78 -0
  135. package/tsconfig.json +9 -0
package/src/fields.ts ADDED
@@ -0,0 +1,173 @@
1
+ import { InputField } from '@segment/actions-core'
2
+
3
+ export const event_name: InputField = {
4
+ label: 'Event Name',
5
+ description: 'The name of the event to track in Mixpanel.',
6
+ required: true,
7
+ type: 'string',
8
+ default: { '@path': '$.event' }
9
+ }
10
+
11
+ export const properties: InputField = {
12
+ label: 'Event Properties',
13
+ description: 'Properties to associate with the event.',
14
+ required: false,
15
+ type: 'object',
16
+ default: { '@path': '$.properties' }
17
+ }
18
+
19
+ export const unique_id: InputField = {
20
+ label: 'Unique ID',
21
+ description: 'The unique ID to associate with the user.',
22
+ required: true,
23
+ type: 'string',
24
+ default: { '@path': '$.userId' }
25
+ }
26
+
27
+ export const user_profile_properties_to_set: InputField = {
28
+ label: 'User Profile Properties to Set',
29
+ description: 'User Profile Properties to set on the user profile in Mixpanel.',
30
+ required: false,
31
+ defaultObjectUI: 'keyvalue',
32
+ additionalProperties: true,
33
+ type: 'object',
34
+ properties: {
35
+ name: {
36
+ label: 'Name',
37
+ description: 'The name of the user.',
38
+ type: 'string'
39
+ },
40
+ first_name: {
41
+ label: 'First Name',
42
+ description: 'The first name of the user.',
43
+ type: 'string'
44
+ },
45
+ last_name: {
46
+ label: 'Last Name',
47
+ description: 'The last name of the user.',
48
+ type: 'string'
49
+ },
50
+ email: {
51
+ label: 'Email',
52
+ description: 'The email of the user.',
53
+ type: 'string',
54
+ format: 'email'
55
+ },
56
+ phone: {
57
+ label: 'Phone',
58
+ description: 'The phone number of the user.',
59
+ type: 'string'
60
+ },
61
+ avatar: {
62
+ label: 'Avatar',
63
+ description: 'The avatar URL of the user.',
64
+ type: 'string',
65
+ format: 'uri'
66
+ },
67
+ created: {
68
+ label: 'Created',
69
+ description: 'The creation date of the user profile.',
70
+ type: 'string',
71
+ format: 'date-time'
72
+ }
73
+ },
74
+ default: {
75
+ name: { '@path': '$.traits.name' },
76
+ first_name: { '@path': '$.traits.first_name' },
77
+ last_name: { '@path': '$.traits.last_name' },
78
+ email: { '@path': '$.traits.email' },
79
+ phone: { '@path': '$.traits.phone' },
80
+ avatar: { '@path': '$.traits.avatar' },
81
+ created: { '@path': '$.traits.created' }
82
+ }
83
+ }
84
+
85
+ export const user_profile_properties_to_set_once: InputField = {
86
+ label: 'User Profile Properties to Set Once',
87
+ description:
88
+ 'User Profile Properties to set once on the user profile in Mixpanel. Values which get set once cannot be overwritten later.',
89
+ required: false,
90
+ defaultObjectUI: 'keyvalue',
91
+ type: 'object'
92
+ }
93
+
94
+ export const user_profile_properties_to_increment: InputField = {
95
+ label: 'User Profile Properties to Increment',
96
+ description: 'User Profile Properties to increment on the user profile in Mixpanel. Values must be numeric.',
97
+ required: false,
98
+ defaultObjectUI: 'keyvalue',
99
+ type: 'object'
100
+ }
101
+
102
+ export const group_details: InputField = {
103
+ label: 'Group Details',
104
+ description: 'Details for the group to be created or updated in Mixpanel.',
105
+ type: 'object',
106
+ defaultObjectUI: 'keyvalue:only',
107
+ additionalProperties: false,
108
+ required: true,
109
+ properties: {
110
+ group_key: {
111
+ label: 'Group Key',
112
+ description:
113
+ 'The Group Key / type of group to associate with the user. This group key should already be defined in your Mixpanel project.',
114
+ required: true,
115
+ type: 'string'
116
+ },
117
+ group_id: {
118
+ label: 'Group ID',
119
+ description: 'The unique ID to associate with the group.',
120
+ required: true,
121
+ type: 'string'
122
+ }
123
+ },
124
+ default: {
125
+ group_key: { '@path': '$.traits.group_key' },
126
+ group_id: { '@path': '$.groupId' }
127
+ }
128
+ }
129
+
130
+ export const group_profile_properties_to_set: InputField = {
131
+ label: 'Group properties to Set',
132
+ description: 'Group Profile Properties to set on the group in Mixpanel.',
133
+ required: false,
134
+ defaultObjectUI: 'keyvalue',
135
+ type: 'object'
136
+ }
137
+
138
+ export const group_profile_properties_to_set_once: InputField = {
139
+ label: 'Group properties to set once',
140
+ description:
141
+ 'Group Profile Properties to set once on the group profile in Mixpanel. Values which get set once cannot be overwritten later.',
142
+ required: false,
143
+ defaultObjectUI: 'keyvalue',
144
+ type: 'object'
145
+ }
146
+
147
+ export const group_profile_properties_to_union: InputField = {
148
+ label: 'Group list properties to union',
149
+ description: 'Merge a list into a list group property. Duplicates will be removed.',
150
+ required: false,
151
+ type: 'object',
152
+ multiple: true,
153
+ defaultObjectUI: 'arrayeditor',
154
+ additionalProperties: false,
155
+ properties: {
156
+ list_name: {
157
+ label: 'List Name',
158
+ description: 'The name of the list property to union values into.',
159
+ type: 'string',
160
+ allowNull: false,
161
+ required: true
162
+ },
163
+ string_values: {
164
+ label: 'Values',
165
+ description:
166
+ 'An array of string values to merge into the list. Non string lists cannot be updated. Duplicates will be removed.',
167
+ type: 'string',
168
+ required: true,
169
+ allowNull: false,
170
+ multiple: true
171
+ }
172
+ }
173
+ }
@@ -0,0 +1,57 @@
1
+ import { Payload as GroupPayload } from './group/generated-types'
2
+ import { Payload as TrackPayload } from './track/generated-types'
3
+ import { Payload as IdentifyPayload } from './identify/generated-types'
4
+ import { Payload as TrackPageViewPayload } from './trackPageView/generated-types'
5
+ import type { Mixpanel } from './types'
6
+
7
+ export function sendIdentify(mixpanel: Mixpanel, payload: IdentifyPayload | TrackPayload | TrackPageViewPayload) {
8
+ const {
9
+ unique_id,
10
+ user_profile_properties_to_set,
11
+ user_profile_properties_to_set_once,
12
+ user_profile_properties_to_increment
13
+ } = payload
14
+
15
+ if (unique_id) {
16
+ mixpanel.identify(unique_id)
17
+ }
18
+
19
+ if (user_profile_properties_to_set && Object.keys(user_profile_properties_to_set).length > 0) {
20
+ mixpanel.people.set(user_profile_properties_to_set)
21
+ }
22
+
23
+ if (user_profile_properties_to_set_once && Object.keys(user_profile_properties_to_set_once).length > 0) {
24
+ mixpanel.people.set_once(user_profile_properties_to_set_once)
25
+ }
26
+
27
+ if (user_profile_properties_to_increment && Object.keys(user_profile_properties_to_increment).length > 0) {
28
+ mixpanel.people.increment(user_profile_properties_to_increment)
29
+ }
30
+ }
31
+
32
+ export function sendGroup(mixpanel: Mixpanel, payload: GroupPayload | TrackPayload | TrackPageViewPayload) {
33
+ const {
34
+ group_details: { group_key, group_id } = {},
35
+ group_profile_properties_to_set,
36
+ group_profile_properties_to_set_once,
37
+ group_profile_properties_to_union
38
+ } = payload
39
+
40
+ if (group_key && group_id) {
41
+ mixpanel.set_group(group_key, group_id)
42
+ const group = mixpanel.get_group(group_key, group_id)
43
+
44
+ if (group_profile_properties_to_set && Object.keys(group_profile_properties_to_set).length > 0) {
45
+ group.set(group_profile_properties_to_set)
46
+ }
47
+ if (group_profile_properties_to_set_once && Object.keys(group_profile_properties_to_set_once).length > 0) {
48
+ group.set_once(group_profile_properties_to_set_once)
49
+ }
50
+ if (group_profile_properties_to_union && group_profile_properties_to_union.length > 0) {
51
+ group_profile_properties_to_union.forEach((item) => {
52
+ const { list_name, string_values } = item
53
+ group.union(list_name, string_values)
54
+ })
55
+ }
56
+ }
57
+ }
@@ -0,0 +1,116 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Settings {
4
+ /**
5
+ * Your Mixpanel project token.
6
+ */
7
+ projectToken: string
8
+ /**
9
+ * The name for the new mixpanel instance that you want created.
10
+ */
11
+ name?: string
12
+ /**
13
+ * The Mixpanel API host to send data to.
14
+ */
15
+ api_host: string
16
+ /**
17
+ * Enable or disable Mixpanel autocapture functionality. Select "Custom" to specify fine grained control over which events are autocaptured.
18
+ */
19
+ autocapture?: string
20
+ /**
21
+ * Capture pageview events automatically
22
+ */
23
+ pageview: string
24
+ /**
25
+ * Capture click events automatically
26
+ */
27
+ click: boolean
28
+ /**
29
+ * Capture dead click events automatically
30
+ */
31
+ dead_click: boolean
32
+ /**
33
+ * Capture input events automatically
34
+ */
35
+ input: boolean
36
+ /**
37
+ * Capture rage click events automatically
38
+ */
39
+ rage_click: boolean
40
+ /**
41
+ * Capture scroll events automatically
42
+ */
43
+ scroll: boolean
44
+ /**
45
+ * Capture form submit events automatically
46
+ */
47
+ submit?: boolean
48
+ /**
49
+ * Capture text content of elements in autocaptured events
50
+ */
51
+ capture_text_content: boolean
52
+ /**
53
+ * Enable or disable cross subdomain cookies for Mixpanel.
54
+ */
55
+ cross_subdomain_cookie?: boolean
56
+ /**
57
+ * Set the persistence method for Mixpanel (cookie or localStorage).
58
+ */
59
+ persistence?: string
60
+ /**
61
+ * Enable or disable tracking of marketing campaigns in Mixpanel. Includes UTM parameters and click identifiers for various ad platforms.
62
+ */
63
+ track_marketing?: boolean
64
+ /**
65
+ * Set the cookie expiration time in days for Mixpanel cookies.
66
+ */
67
+ cookie_expiration?: number
68
+ /**
69
+ * Disable all persistence mechanisms for Mixpanel.
70
+ */
71
+ disable_persistence?: boolean
72
+ /**
73
+ * Enable or disable sending IP address information to Mixpanel.
74
+ */
75
+ ip?: boolean
76
+ /**
77
+ * CSS class to block elements from being recorded in session recordings.
78
+ */
79
+ record_block_class?: string
80
+ /**
81
+ * CSS selector to block elements from being recorded in session recordings.
82
+ */
83
+ record_block_selector?: string
84
+ /**
85
+ * Enable or disable recording of canvas elements in session recordings.
86
+ */
87
+ record_canvas?: boolean
88
+ /**
89
+ * Enable or disable tracking of heatmap events in session recordings.
90
+ */
91
+ record_heatmap_data?: boolean
92
+ /**
93
+ * Idle timeout in milliseconds for session recordings.
94
+ */
95
+ record_idle_timeout_ms?: number
96
+ /**
97
+ * CSS class to mask text elements in session recordings.
98
+ */
99
+ record_mask_text_class?: string
100
+ /**
101
+ * CSS selector to mask text elements in session recordings.
102
+ */
103
+ record_mask_text_selector?: string
104
+ /**
105
+ * Maximum recording time in milliseconds for session recordings.
106
+ */
107
+ record_max_ms?: number
108
+ /**
109
+ * Minimum recording time in milliseconds for session recordings.
110
+ */
111
+ record_min_ms?: number
112
+ /**
113
+ * Percentage of sessions to record for session recordings.
114
+ */
115
+ record_sessions_percent?: number
116
+ }
@@ -0,0 +1,126 @@
1
+ import { Analytics, Context } from '@segment/analytics-next'
2
+ import { Subscription } from '@segment/browser-destination-runtime'
3
+ import MixpanelDestination, { destination } from '../../index'
4
+ import { Mixpanel } from '../../types'
5
+ import { AUTOCAPTURE_OPTIONS, PERSISTENCE_OPTIONS } from '../../constants'
6
+ import { Group } from '../../types'
7
+
8
+ describe('Mixpanel.group', () => {
9
+ const settings = {
10
+ projectToken: 'projectToken1',
11
+ name: 'name1',
12
+ default: 'https://api-js.mixpanel.com',
13
+ autocapture: AUTOCAPTURE_OPTIONS.ENABLED,
14
+ cross_subdomain_cookie: true,
15
+ persistence: PERSISTENCE_OPTIONS.COOKIE,
16
+ track_marketing: true,
17
+ cookie_expiration: 365,
18
+ disable_persistence: false,
19
+ ip: true,
20
+ record_block_class: 'mp-block',
21
+ record_block_selector: 'img, video, audio',
22
+ record_canvas: false,
23
+ record_heatmap_data: false,
24
+ record_idle_timeout_ms: 180_000,
25
+ record_mask_text_class: 'mp-mask',
26
+ record_mask_text_selector: '*',
27
+ record_max_ms: 86_400_000,
28
+ record_min_ms: 8_000,
29
+ record_sessions_percent: 0
30
+ }
31
+
32
+ let mockMPP: Mixpanel
33
+ let mockGroup: Group
34
+ let event: any
35
+
36
+ beforeEach(async () => {
37
+ jest.restoreAllMocks()
38
+ jest.spyOn(destination, 'initialize').mockImplementation(() => {
39
+ mockGroup = {
40
+ set: jest.fn(),
41
+ set_once: jest.fn(),
42
+ union: jest.fn()
43
+ }
44
+
45
+ mockMPP = {
46
+ init: jest.fn(),
47
+ track_pageview: jest.fn(),
48
+ track: jest.fn(),
49
+ identify: jest.fn(),
50
+ alias: jest.fn(),
51
+ get_group: jest.fn().mockReturnValue(mockGroup),
52
+ set_group: jest.fn(),
53
+ people: {
54
+ set: jest.fn(),
55
+ set_once: jest.fn(),
56
+ increment: jest.fn()
57
+ }
58
+ }
59
+ return Promise.resolve(mockMPP)
60
+ })
61
+ })
62
+
63
+ test('group() handled correctly', async () => {
64
+ const subscriptions: Subscription[] = [
65
+ {
66
+ partnerAction: 'group',
67
+ name: 'Group',
68
+ enabled: true,
69
+ subscribe: 'type = "group"',
70
+ mapping: {
71
+ group_details: {
72
+ group_key: { '@path': '$.traits.group_key' },
73
+ group_id: { '@path': '$.groupId' }
74
+ },
75
+ group_profile_properties_to_set: {
76
+ company_name: { '@path': '$.traits.company_name' },
77
+ number_employees: { '@path': '$.traits.number_employees' }
78
+ },
79
+ group_profile_properties_to_set_once: {
80
+ set_once_trait: { '@path': '$.traits.set_once_trait_1' }
81
+ },
82
+ group_profile_properties_to_union: { '@path': '$.traits.union_properties' }
83
+ }
84
+ }
85
+ ]
86
+
87
+ const context = new Context({
88
+ messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
89
+ type: 'group',
90
+ anonymousId: 'anonymousId',
91
+ userId: 'userId1',
92
+ groupId: 'groupId1',
93
+ traits: {
94
+ group_key: 'company',
95
+ company_name: 'MicroMegaCorpSoftware',
96
+ number_employees: 1000,
97
+ set_once_trait_1: 'set_once_value_1',
98
+ union_properties: [
99
+ { list_name: 'Interests', string_values: ['sports', 'music'] },
100
+ { list_name: 'Regions', string_values: ['north-america', 'europe'] }
101
+ ]
102
+ }
103
+ })
104
+
105
+ const [groupEvent] = await MixpanelDestination({
106
+ ...settings,
107
+ subscriptions
108
+ })
109
+ event = groupEvent
110
+
111
+ await event.load(Context.system(), {} as Analytics)
112
+ await event.group?.(context)
113
+ expect(mockMPP.set_group).toHaveBeenCalledWith('company', 'groupId1')
114
+ expect(mockMPP.get_group).toHaveBeenCalledWith('company', 'groupId1')
115
+ expect(mockGroup.set).toHaveBeenCalledWith({
116
+ company_name: 'MicroMegaCorpSoftware',
117
+ number_employees: 1000
118
+ })
119
+ expect(mockGroup.set_once).toHaveBeenCalledWith({
120
+ set_once_trait: 'set_once_value_1'
121
+ })
122
+ expect(mockGroup.union).toHaveBeenCalledTimes(2)
123
+ expect(mockGroup.union).toHaveBeenNthCalledWith(1, 'Interests', ['sports', 'music'])
124
+ expect(mockGroup.union).toHaveBeenNthCalledWith(2, 'Regions', ['north-america', 'europe'])
125
+ })
126
+ })
@@ -0,0 +1,42 @@
1
+ // Generated file. DO NOT MODIFY IT BY HAND.
2
+
3
+ export interface Payload {
4
+ /**
5
+ * Details for the group to be created or updated in Mixpanel.
6
+ */
7
+ group_details: {
8
+ /**
9
+ * The Group Key / type of group to associate with the user. This group key should already be defined in your Mixpanel project.
10
+ */
11
+ group_key: string
12
+ /**
13
+ * The unique ID to associate with the group.
14
+ */
15
+ group_id: string
16
+ }
17
+ /**
18
+ * Group Profile Properties to set on the group in Mixpanel.
19
+ */
20
+ group_profile_properties_to_set?: {
21
+ [k: string]: unknown
22
+ }
23
+ /**
24
+ * Group Profile Properties to set once on the group profile in Mixpanel. Values which get set once cannot be overwritten later.
25
+ */
26
+ group_profile_properties_to_set_once?: {
27
+ [k: string]: unknown
28
+ }
29
+ /**
30
+ * Merge a list into a list group property. Duplicates will be removed.
31
+ */
32
+ group_profile_properties_to_union?: {
33
+ /**
34
+ * The name of the list property to union values into.
35
+ */
36
+ list_name: string
37
+ /**
38
+ * An array of string values to merge into the list. Non string lists cannot be updated. Duplicates will be removed.
39
+ */
40
+ string_values: string[]
41
+ }[]
42
+ }
@@ -0,0 +1,29 @@
1
+ import type { BrowserActionDefinition } from '@segment/browser-destination-runtime/types'
2
+ import type { Settings } from '../generated-types'
3
+ import type { Payload } from './generated-types'
4
+ import type { Mixpanel } from '../types'
5
+ import { sendGroup } from '../functions'
6
+ import {
7
+ group_details,
8
+ group_profile_properties_to_set,
9
+ group_profile_properties_to_set_once,
10
+ group_profile_properties_to_union
11
+ } from '../fields'
12
+
13
+ const action: BrowserActionDefinition<Settings, Mixpanel, Payload> = {
14
+ title: 'Group',
15
+ description: 'Sync Group data to Mixpanel.',
16
+ defaultSubscription: 'type = "group"',
17
+ platform: 'web',
18
+ fields: {
19
+ group_details,
20
+ group_profile_properties_to_set,
21
+ group_profile_properties_to_set_once,
22
+ group_profile_properties_to_union
23
+ },
24
+ perform: (mixpanel, { payload }) => {
25
+ sendGroup(mixpanel, payload)
26
+ }
27
+ }
28
+
29
+ export default action
@@ -0,0 +1,135 @@
1
+ import { Analytics, Context } from '@segment/analytics-next'
2
+ import { Subscription } from '@segment/browser-destination-runtime'
3
+ import MixpanelDestination, { destination } from '../../index'
4
+ import { Mixpanel } from '../../types'
5
+ import { AUTOCAPTURE_OPTIONS, PERSISTENCE_OPTIONS } from '../../constants'
6
+ import { Group } from '../../types'
7
+
8
+ describe('Mixpanel.identify', () => {
9
+ const settings = {
10
+ projectToken: 'projectToken1',
11
+ name: 'name1',
12
+ default: 'https://api-js.mixpanel.com',
13
+ autocapture: AUTOCAPTURE_OPTIONS.ENABLED,
14
+ cross_subdomain_cookie: true,
15
+ persistence: PERSISTENCE_OPTIONS.COOKIE,
16
+ track_marketing: true,
17
+ cookie_expiration: 365,
18
+ disable_persistence: false,
19
+ ip: true,
20
+ record_block_class: 'mp-block',
21
+ record_block_selector: 'img, video, audio',
22
+ record_canvas: false,
23
+ record_heatmap_data: false,
24
+ record_idle_timeout_ms: 180_000,
25
+ record_mask_text_class: 'mp-mask',
26
+ record_mask_text_selector: '*',
27
+ record_max_ms: 86_400_000,
28
+ record_min_ms: 8_000,
29
+ record_sessions_percent: 0
30
+ }
31
+
32
+ let mockMPP: Mixpanel
33
+ let mockGroup: Group
34
+ let event: any
35
+
36
+ beforeEach(async () => {
37
+ jest.restoreAllMocks()
38
+ jest.spyOn(destination, 'initialize').mockImplementation(() => {
39
+ mockGroup = {
40
+ set: jest.fn(),
41
+ set_once: jest.fn(),
42
+ union: jest.fn()
43
+ }
44
+
45
+ mockMPP = {
46
+ init: jest.fn(),
47
+ track_pageview: jest.fn(),
48
+ track: jest.fn(),
49
+ identify: jest.fn(),
50
+ alias: jest.fn(),
51
+ get_group: jest.fn().mockReturnValue(mockGroup),
52
+ set_group: jest.fn(),
53
+ people: {
54
+ set: jest.fn(),
55
+ set_once: jest.fn(),
56
+ increment: jest.fn()
57
+ }
58
+ }
59
+ return Promise.resolve(mockMPP)
60
+ })
61
+ })
62
+
63
+ test('identify() handled correctly', async () => {
64
+ const subscriptions: Subscription[] = [
65
+ {
66
+ partnerAction: 'identify',
67
+ name: 'Identify',
68
+ enabled: true,
69
+ subscribe: 'type = "identify"',
70
+ mapping: {
71
+ unique_id: { '@path': '$.userId' },
72
+ user_profile_properties_to_set: {
73
+ name: { '@path': '$.traits.name' },
74
+ first_name: { '@path': '$.traits.first_name' },
75
+ last_name: { '@path': '$.traits.last_name' },
76
+ email: { '@path': '$.traits.email' },
77
+ phone: { '@path': '$.traits.phone' },
78
+ avatar: { '@path': '$.traits.avatar' },
79
+ created: { '@path': '$.traits.created' }
80
+ },
81
+ user_profile_properties_to_set_once: {
82
+ set_once_trait: { '@path': '$.traits.set_once_trait_1' }
83
+ },
84
+ user_profile_properties_to_increment: {
85
+ increment_property: { '@path': '$.traits.increment_property_1' }
86
+ }
87
+ }
88
+ }
89
+ ]
90
+
91
+ const context = new Context({
92
+ messageId: 'ajs-71f386523ee5dfa90c7d0fda28b6b5c6',
93
+ type: 'identify',
94
+ anonymousId: 'anonymousId',
95
+ userId: 'userId1',
96
+ traits: {
97
+ name: 'name1',
98
+ last_name: 'lastName1',
99
+ first_name: 'firstName1',
100
+ email: 'aaa@aaa.com',
101
+ phone: '+12345678900',
102
+ avatar: 'https://example.com/avatar.png',
103
+ created: '2020-01-01T00:05:02.010Z',
104
+ set_once_trait_1: 'set_once_value_1',
105
+ increment_property_1: 5
106
+ }
107
+ })
108
+
109
+ const [identifyEvent] = await MixpanelDestination({
110
+ ...settings,
111
+ subscriptions
112
+ })
113
+ event = identifyEvent
114
+
115
+ await event.load(Context.system(), {} as Analytics)
116
+ await event.identify?.(context)
117
+
118
+ expect(mockMPP.identify).toHaveBeenCalledWith('userId1')
119
+ expect(mockMPP.people.set).toHaveBeenCalledWith({
120
+ name: 'name1',
121
+ last_name: 'lastName1',
122
+ first_name: 'firstName1',
123
+ email: 'aaa@aaa.com',
124
+ phone: '+12345678900',
125
+ avatar: 'https://example.com/avatar.png',
126
+ created: '2020-01-01T00:05:02.010Z'
127
+ })
128
+ expect(mockMPP.people.set_once).toHaveBeenCalledWith({
129
+ set_once_trait: 'set_once_value_1'
130
+ })
131
+ expect(mockMPP.people.increment).toHaveBeenCalledWith({
132
+ increment_property: 5
133
+ })
134
+ })
135
+ })