From 892ff4cd1d5815103eb5fc25ff99ce35f1a401f1 Mon Sep 17 00:00:00 2001 From: hassaantahir0 Date: Fri, 3 Apr 2026 16:09:56 +0000 Subject: [PATCH 01/11] feat: automated TS Serving API update --- packages/types/src/config/types.gen.ts | 86 ++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) diff --git a/packages/types/src/config/types.gen.ts b/packages/types/src/config/types.gen.ts index 52935bc9..4eb247f4 100644 --- a/packages/types/src/config/types.gen.ts +++ b/packages/types/src/config/types.gen.ts @@ -39,6 +39,44 @@ export const ConfigAudienceTypes = { TRANSIENT: 'transient' } as const; +/** + * Account billing status + */ +export type PlanStatus = 'paid' | 'trial' | 'trialExpired' | 'canceled' | 'paused'; + +/** + * Account billing status + */ +export const PlanStatus = { + PAID: 'paid', + TRIAL: 'trial', + TRIAL_EXPIRED: 'trialExpired', + CANCELED: 'canceled', + PAUSED: 'paused' +} as const; + +/** + * The Convert product line this billing plan pertains to. + * - `experiences`: Relates to A/B testing, MVT, Split URL, and personalization features. + * - `deploy`: Relates to the "Deploy" feature for rolling out changes to specific audiences without A/B testing reports. Knowledge Base: "Deployments have the potential to contain small segments...and this could be interpreted by Privacy Authorities in Europe as identification of data subjects." + * - `addons`: Relates to add-on products that extend the core platform capabilities. + * + */ +export type Products = 'experiences' | 'deploy' | 'addons'; + +/** + * The Convert product line this billing plan pertains to. + * - `experiences`: Relates to A/B testing, MVT, Split URL, and personalization features. + * - `deploy`: Relates to the "Deploy" feature for rolling out changes to specific audiences without A/B testing reports. Knowledge Base: "Deployments have the potential to contain small segments...and this could be interpreted by Privacy Authorities in Europe as identification of data subjects." + * - `addons`: Relates to add-on products that extend the core platform capabilities. + * + */ +export const Products = { + EXPERIENCES: 'experiences', + DEPLOY: 'deploy', + ADDONS: 'addons' +} as const; + export type PageNumber = { /** * The page number for paginated results. For example, if `results_per_page` is 30, `page: 2` will retrieve items 31-60. @@ -933,8 +971,35 @@ export type VisitorInsightsBase = { * */ obfuscate_text?: boolean; + /** + * The percentage of visitors included in sampling for Convert Signals session recordings and Heatmaps for this project. + * Higher values collect data from a larger share of traffic and consume allocation faster. + * + */ + sampling_rate?: 5 | 10 | 20 | 30 | 40 | 50; }; +/** + * The percentage of visitors included in sampling for Convert Signals session recordings and Heatmaps for this project. + * Higher values collect data from a larger share of traffic and consume allocation faster. + * + */ +export type sampling_rate = 5 | 10 | 20 | 30 | 40 | 50; + +/** + * The percentage of visitors included in sampling for Convert Signals session recordings and Heatmaps for this project. + * Higher values collect data from a larger share of traffic and consume allocation faster. + * + */ +export const sampling_rate = { + '_5': 5, + '_10': 10, + '_20': 20, + '_30': 30, + '_40': 40, + '_50': 50 +} as const; + /** * The method used for detecting and handling order outliers in revenue or product count tracking: * - `none`: No outlier detection is applied. @@ -1597,7 +1662,7 @@ export type UpdateExperienceChangeRequestData = ExperienceChangeAdd; * Knowledge Base has many articles on integrations, e.g., "Integrate Convert Experiences with Google Analytics", "Hotjar Integration". * */ -export type IntegrationProvider = 'baidu' | 'clicktale' | 'clicky' | 'cnzz' | 'crazyegg' | 'econda' | 'eulerian' | 'google_analytics' | 'gosquared' | 'heapanalytics' | 'hotjar' | 'mixpanel' | 'mouseflow' | 'piwik' | 'segmentio' | 'sitecatalyst' | 'woopra' | 'ysance'; +export type IntegrationProvider = 'baidu' | 'clicktale' | 'clicky' | 'cnzz' | 'crazyegg' | 'econda' | 'eulerian' | 'google_analytics' | 'gosquared' | 'heapanalytics' | 'hotjar' | 'microsoft_clarity' | 'mixpanel' | 'mouseflow' | 'piwik' | 'segmentio' | 'sitecatalyst' | 'woopra' | 'ysance'; /** * Identifies the third-party analytics, heatmap, or data platform with which Convert Experiences is integrated for this specific experience. @@ -1617,6 +1682,7 @@ export const IntegrationProvider = { GOSQUARED: 'gosquared', HEAPANALYTICS: 'heapanalytics', HOTJAR: 'hotjar', + MICROSOFT_CLARITY: 'microsoft_clarity', MIXPANEL: 'mixpanel', MOUSEFLOW: 'mouseflow', PIWIK: 'piwik', @@ -1692,6 +1758,13 @@ export type ExperienceIntegrationHeapanalytics = ExperienceIntegrationBase; export type ExperienceIntegrationHotjar = ExperienceIntegrationBase; +/** + * Configuration for Microsoft Clarity. When enabled, experiment context can be sent for segmentation in Clarity recordings and heatmaps. + * No provider-specific settings beyond `enabled` are required; the Clarity project ID is configured in your site’s global JavaScript. + * + */ +export type ExperienceIntegrationMicrosoftClarity = ExperienceIntegrationBase; + export type ExperienceIntegrationMixpanel = ExperienceIntegrationBase; export type ExperienceIntegrationMouseflow = ExperienceIntegrationBase; @@ -2400,6 +2473,10 @@ export type ConfigProject = { * Custom domain to be used instead of standard Convert's one */ domain?: string; + /** + * The version of the custom domain. + */ + readonly version?: string; } | null; /** * List of domains allowed to be tracked under this project @@ -2752,7 +2829,7 @@ export type VisitorSegments = { /** * Traffic source */ - source?: 'campaign' | 'search' | 'referral' | 'direct'; + source?: 'campaign' | 'search' | 'referral' | 'direct' | 'ai_tool'; /** * Campaign string */ @@ -2805,7 +2882,7 @@ export const browser = { /** * Traffic source */ -export type source = 'campaign' | 'search' | 'referral' | 'direct'; +export type source = 'campaign' | 'search' | 'referral' | 'direct' | 'ai_tool'; /** * Traffic source @@ -2814,7 +2891,8 @@ export const source = { CAMPAIGN: 'campaign', SEARCH: 'search', REFERRAL: 'referral', - DIRECT: 'direct' + DIRECT: 'direct', + AI_TOOL: 'ai_tool' } as const; /** From 1178fb5a51ef2ea3443af70433aa751e3a2d6044 Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Mon, 6 Apr 2026 21:33:00 +0200 Subject: [PATCH 02/11] chore(ci): migrate remaining workflows from Node 18 to Node 22 Update pages, publish-package, and release-please workflows to use Node 22, matching the QA workflow that already runs on Node 22. --- .github/workflows/pages.yml | 2 +- .github/workflows/publish-package.yml | 2 +- .github/workflows/release-please.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 2121074c..568c1c56 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: [18] + node: [22] # Steps represent a sequence of tasks that will be executed as part of the job steps: - uses: actions/setup-node@v1 diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index 70c86d96..2eb48e88 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -15,7 +15,7 @@ jobs: # Setup .npmrc file to publish to npm - uses: actions/setup-node@v4 with: - node-version: '18.x' + node-version: '22.x' registry-url: 'https://registry.npmjs.org' - name: Resolve tag run: echo "RELEASE_TAG=${{ github.event.release.tag_name || inputs.tag }}" >> $GITHUB_ENV diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index cb9142e2..9fd5005a 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 22 registry-url: https://registry.npmjs.org - name: Install deps run: | From 273990d7727e4b1e738a33a5bfa1508c2e8c5716 Mon Sep 17 00:00:00 2001 From: hassaantahir0 Date: Wed, 8 Apr 2026 10:38:34 +0000 Subject: [PATCH 03/11] feat: automated TS Serving API update --- packages/types/src/config/types.gen.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/packages/types/src/config/types.gen.ts b/packages/types/src/config/types.gen.ts index 4eb247f4..b0dfc202 100644 --- a/packages/types/src/config/types.gen.ts +++ b/packages/types/src/config/types.gen.ts @@ -619,7 +619,7 @@ export type VisitorDataExistsMatchRule = BaseRuleWithBooleanValue & { export type CookieMatchRule = BaseRuleWithStringValue & { rule_type: CookieMatchRulesTypes; matching?: (BaseMatch & { - match_type?: TextMatchingOptions; + match_type?: CookieMatchingOptions; }); /** * The name of the cookie which value is compared to the given rule value @@ -734,6 +734,18 @@ export const TextMatchingOptions = { STARTS_WITH: 'startsWith' } as const; +export type CookieMatchingOptions = 'matches' | 'regexMatches' | 'contains' | 'endsWith' | 'startsWith' | 'exists' | 'doesNotExist'; + +export const CookieMatchingOptions = { + MATCHES: 'matches', + REGEX_MATCHES: 'regexMatches', + CONTAINS: 'contains', + ENDS_WITH: 'endsWith', + STARTS_WITH: 'startsWith', + EXISTS: 'exists', + DOES_NOT_EXIST: 'doesNotExist' +} as const; + export type NumericMatchingOptions = 'equalsNumber' | 'less' | 'lessEqual'; export const NumericMatchingOptions = { From 8183b67d4aeb22a2627f07b60313cc3dc8b844d7 Mon Sep 17 00:00:00 2001 From: Joseph Samir Date: Wed, 15 Apr 2026 15:48:20 +0200 Subject: [PATCH 04/11] feat: adding cookie (exist , not exist) conditions --- packages/rules/src/rule-manager.ts | 29 +++-- packages/rules/tests/rule-manager.tests.ts | 118 +++++++++++++++++++++ packages/utils/src/comparisons.ts | 20 ++++ packages/utils/tests/comparisons.tests.ts | 23 ++++ 4 files changed, 184 insertions(+), 6 deletions(-) diff --git a/packages/rules/src/rule-manager.ts b/packages/rules/src/rule-manager.ts index 4422ebeb..318ee8c0 100644 --- a/packages/rules/src/rule-manager.ts +++ b/packages/rules/src/rule-manager.ts @@ -15,6 +15,7 @@ import {RuleManagerInterface} from './interfaces/rule-manager'; import { Config, + CookieMatchingOptions, RuleElement, RuleAnd, RuleOrWhen, @@ -165,15 +166,19 @@ export class RuleManager implements RuleManagerInterface { rule: rule }) ); - return ( + const hasMatching = Object.prototype.hasOwnProperty.call(rule, 'matching') && typeof rule.matching === 'object' && Object.prototype.hasOwnProperty.call(rule.matching, 'match_type') && typeof rule.matching.match_type === 'string' && Object.prototype.hasOwnProperty.call(rule.matching, 'negated') && - typeof rule.matching.negated === 'boolean' && - Object.prototype.hasOwnProperty.call(rule, 'value') - ); + typeof rule.matching.negated === 'boolean'; + if (!hasMatching) return false; + const matchType = rule.matching.match_type as string; + if (matchType === CookieMatchingOptions.EXISTS || matchType === CookieMatchingOptions.DOES_NOT_EXIST) { + return true; + } + return Object.prototype.hasOwnProperty.call(rule, 'value'); } /** @@ -263,7 +268,7 @@ export class RuleManager implements RuleManagerInterface { if (this.isValidRule(rule)) { try { const negation = rule.matching.negated || false; - const matching = rule.matching.match_type; + const matching = rule.matching.match_type as string; if (this.getComparisonProcessorMethods().indexOf(matching) !== -1) { if (data && typeof data === 'object') { // Validate data key-value set. @@ -314,7 +319,19 @@ export class RuleManager implements RuleManagerInterface { ); } } - } else { + } + // Key not found or data empty — for existence operators, evaluate with undefined + if ( + matching === CookieMatchingOptions.EXISTS || + matching === CookieMatchingOptions.DOES_NOT_EXIST + ) { + return this._comparisonProcessor[matching]( + undefined, + rule.value, + negation + ); + } + if (!objectNotEmpty(data) && !this.isUsingCustomInterface(data)) { this._loggerManager?.trace?.('RuleManager._processRuleItem()', { warn: ERROR_MESSAGES.RULE_DATA_NOT_VALID, data diff --git a/packages/rules/tests/rule-manager.tests.ts b/packages/rules/tests/rule-manager.tests.ts index cacc671f..2b96fb78 100644 --- a/packages/rules/tests/rule-manager.tests.ts +++ b/packages/rules/tests/rule-manager.tests.ts @@ -534,6 +534,124 @@ describe('RuleManager tests', function () { expect(ruleManager.isRuleMatched(data32, testRuleSet3)).to.equal(true); } ); + it('isValidRule should return true for exists rule without value', function () { + expect( + ruleManager.isValidRule({ + key: 'myCookie', + matching: { + match_type: 'exists', + negated: false + } + }) + ).to.equal(true); + }); + it('isValidRule should return true for doesNotExist rule without value', function () { + expect( + ruleManager.isValidRule({ + key: 'myCookie', + matching: { + match_type: 'doesNotExist', + negated: false + } + }) + ).to.equal(true); + }); + it('isRuleMatched should return true for exists when key is present', function () { + const data = {myCookie: 'someValue'}; + const ruleSet = { + OR: [ + { + AND: [ + { + OR_WHEN: [ + { + key: 'myCookie', + matching: { + match_type: 'exists', + negated: false + }, + value: '' + } + ] + } + ] + } + ] + }; + expect(ruleManager.isRuleMatched(data, ruleSet)).to.equal(true); + }); + it('isRuleMatched should return false for exists when key is not present', function () { + const data = {otherCookie: 'someValue'}; + const ruleSet = { + OR: [ + { + AND: [ + { + OR_WHEN: [ + { + key: 'myCookie', + matching: { + match_type: 'exists', + negated: false + }, + value: '' + } + ] + } + ] + } + ] + }; + expect(ruleManager.isRuleMatched(data, ruleSet)).to.equal(false); + }); + it('isRuleMatched should return true for doesNotExist when key is not present', function () { + const data = {otherCookie: 'someValue'}; + const ruleSet = { + OR: [ + { + AND: [ + { + OR_WHEN: [ + { + key: 'myCookie', + matching: { + match_type: 'doesNotExist', + negated: false + }, + value: '' + } + ] + } + ] + } + ] + }; + expect(ruleManager.isRuleMatched(data, ruleSet)).to.equal(true); + }); + it('isRuleMatched should return false for doesNotExist when key is present', function () { + const data = {myCookie: 'someValue'}; + const ruleSet = { + OR: [ + { + AND: [ + { + OR_WHEN: [ + { + key: 'myCookie', + matching: { + match_type: 'doesNotExist', + negated: false + }, + value: '' + } + ] + } + ] + } + ] + }; + expect(ruleManager.isRuleMatched(data, ruleSet)).to.equal(false); + }); it('Should allow to change comparison processor on fly', function () { const customComparisonProcessor = { isTypeOf: function ( diff --git a/packages/utils/src/comparisons.ts b/packages/utils/src/comparisons.ts index a3b74667..087a4e6a 100644 --- a/packages/utils/src/comparisons.ts +++ b/packages/utils/src/comparisons.ts @@ -151,6 +151,26 @@ export class Comparisons { return this._returnNegationCheck(regExp.test(value), negation); } + static exists( + value: string | number | undefined | null, + testAgainst?: any, + negation?: boolean + ): boolean { + const valueExists = value !== undefined && value !== null && value !== ''; + return this._returnNegationCheck(valueExists, negation); + } + + static not_exists( + value: string | number | undefined | null, + testAgainst?: any, + negation?: boolean + ): boolean { + const valueNotExists = value === undefined || value === null || value === ''; + return this._returnNegationCheck(valueNotExists, negation); + } + + static doesNotExist = this.not_exists; + private static _returnNegationCheck( value: boolean, negation = false diff --git a/packages/utils/tests/comparisons.tests.ts b/packages/utils/tests/comparisons.tests.ts index 6f3dd521..28fac028 100644 --- a/packages/utils/tests/comparisons.tests.ts +++ b/packages/utils/tests/comparisons.tests.ts @@ -319,5 +319,28 @@ describe('Comparison Processor utils tests', function () { ); expect(result).to.equal(false); }); + // Existence operator tests — 'exists' expects true when value is present, + // 'not_exists' and 'doesNotExist' expect the inverse. + const existenceCases: {input: any; label: string; negation?: boolean}[] = [ + {input: 'cookieValue', label: 'a non-empty string value'}, + {input: 123, label: 'a numeric value'}, + {input: undefined, label: 'undefined'}, + {input: null, label: 'null'}, + {input: '', label: 'empty string'}, + {input: 'cookieValue', label: 'non-empty string with negation', negation: true}, + {input: undefined, label: 'undefined with negation', negation: true} + ]; + for (const method of ['exists', 'not_exists', 'doesNotExist'] as const) { + for (const {input, label, negation} of existenceCases) { + const valuePresent = input !== undefined && input !== null && input !== ''; + const isExistsMethod = method === 'exists'; + const baseResult = isExistsMethod ? valuePresent : !valuePresent; + const expected = negation ? !baseResult : baseResult; + it(`${method} should return ${expected} for ${label}`, function () { + const result = Comparisons[method](input, null, negation); + expect(result).to.equal(expected); + }); + } + } /* eslint-enable */ }); From 023151d313c518d2d7a35d9e7785a7dbad22f710 Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Mon, 6 Apr 2026 21:15:57 +0200 Subject: [PATCH 05/11] chore: trigger QA workflow for release PR From 4f3f41f4291aaf147b701d917739aff669adce52 Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Mon, 18 May 2026 21:11:29 +0300 Subject: [PATCH 06/11] chore(deps): sync workspace peer dep ranges to latest published Bumps @convertcom/js-sdk-types peer range to >=3.11.0 across api, bucketing, data, event, experience, js-sdk, rules, segments; bumps @convertcom/js-sdk-rules to >=2.1.4 in data, js-sdk, segments. Picked up by yarn 4 during a local build. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/api/package.json | 4 ++-- packages/bucketing/package.json | 4 ++-- packages/data/package.json | 6 +++--- packages/event/package.json | 4 ++-- packages/experience/package.json | 4 ++-- packages/js-sdk/package.json | 6 +++--- packages/logger/package.json | 2 +- packages/rules/package.json | 4 ++-- packages/segments/package.json | 6 +++--- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- 11 files changed, 22 insertions(+), 22 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index b9597b9a..511d45e4 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -74,7 +74,7 @@ "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-event": ">=2.1.3", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0", + "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} +} \ No newline at end of file diff --git a/packages/bucketing/package.json b/packages/bucketing/package.json index ee09e6c4..de00f793 100644 --- a/packages/bucketing/package.json +++ b/packages/bucketing/package.json @@ -73,7 +73,7 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0", + "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} +} \ No newline at end of file diff --git a/packages/data/package.json b/packages/data/package.json index 2433447f..87d6f2e2 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -76,8 +76,8 @@ "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-event": ">=2.1.3", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-rules": ">=2.1.3", - "@convertcom/js-sdk-types": ">=3.9.0", + "@convertcom/js-sdk-rules": ">=2.1.4", + "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} +} \ No newline at end of file diff --git a/packages/event/package.json b/packages/event/package.json index cc7341d6..9e5fe02b 100644 --- a/packages/event/package.json +++ b/packages/event/package.json @@ -73,6 +73,6 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" } -} +} \ No newline at end of file diff --git a/packages/experience/package.json b/packages/experience/package.json index babb2fc6..e3ca428d 100644 --- a/packages/experience/package.json +++ b/packages/experience/package.json @@ -74,6 +74,6 @@ "@convertcom/js-sdk-data": ">=3.3.3", "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" } -} +} \ No newline at end of file diff --git a/packages/js-sdk/package.json b/packages/js-sdk/package.json index 26d93ee1..9d730582 100644 --- a/packages/js-sdk/package.json +++ b/packages/js-sdk/package.json @@ -94,9 +94,9 @@ "@convertcom/js-sdk-event": ">=2.1.3", "@convertcom/js-sdk-experience": ">=2.3.2", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-rules": ">=2.1.3", + "@convertcom/js-sdk-rules": ">=2.1.4", "@convertcom/js-sdk-segments": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0", + "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} +} \ No newline at end of file diff --git a/packages/logger/package.json b/packages/logger/package.json index 646130d8..f502921f 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -70,4 +70,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} +} \ No newline at end of file diff --git a/packages/rules/package.json b/packages/rules/package.json index 1f18482d..11421cce 100644 --- a/packages/rules/package.json +++ b/packages/rules/package.json @@ -73,7 +73,7 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-types": ">=3.9.0", + "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} +} \ No newline at end of file diff --git a/packages/segments/package.json b/packages/segments/package.json index 60e7b7ad..50966935 100644 --- a/packages/segments/package.json +++ b/packages/segments/package.json @@ -74,7 +74,7 @@ "@convertcom/js-sdk-data": ">=3.3.3", "@convertcom/js-sdk-enums": ">=2.3.0", "@convertcom/js-sdk-logger": ">=2.1.2", - "@convertcom/js-sdk-rules": ">=2.1.3", - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-rules": ">=2.1.4", + "@convertcom/js-sdk-types": ">=3.11.0" } -} +} \ No newline at end of file diff --git a/packages/types/package.json b/packages/types/package.json index eaad2997..e260c057 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -53,4 +53,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} +} \ No newline at end of file diff --git a/packages/utils/package.json b/packages/utils/package.json index e346cb46..4303f081 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -74,4 +74,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} +} \ No newline at end of file From a85ad9993b12660b61eb2d3a9d0ce79d54779a2d Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Mon, 18 May 2026 21:22:29 +0300 Subject: [PATCH 07/11] chore: update yarn lock --- packages/api/package.json | 2 +- packages/bucketing/package.json | 2 +- packages/data/package.json | 2 +- packages/event/package.json | 2 +- packages/experience/package.json | 2 +- packages/js-sdk/package.json | 2 +- packages/logger/package.json | 2 +- packages/rules/package.json | 2 +- packages/segments/package.json | 2 +- packages/types/package.json | 2 +- packages/utils/package.json | 2 +- yarn.lock | 24 ++++++++++++------------ 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/packages/api/package.json b/packages/api/package.json index 511d45e4..553fd8d2 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -77,4 +77,4 @@ "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} \ No newline at end of file +} diff --git a/packages/bucketing/package.json b/packages/bucketing/package.json index de00f793..be942ddf 100644 --- a/packages/bucketing/package.json +++ b/packages/bucketing/package.json @@ -76,4 +76,4 @@ "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} \ No newline at end of file +} diff --git a/packages/data/package.json b/packages/data/package.json index 87d6f2e2..441cd34b 100644 --- a/packages/data/package.json +++ b/packages/data/package.json @@ -80,4 +80,4 @@ "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} \ No newline at end of file +} diff --git a/packages/event/package.json b/packages/event/package.json index 9e5fe02b..29e97ab6 100644 --- a/packages/event/package.json +++ b/packages/event/package.json @@ -75,4 +75,4 @@ "@convertcom/js-sdk-logger": ">=2.1.2", "@convertcom/js-sdk-types": ">=3.11.0" } -} \ No newline at end of file +} diff --git a/packages/experience/package.json b/packages/experience/package.json index e3ca428d..78eb07c2 100644 --- a/packages/experience/package.json +++ b/packages/experience/package.json @@ -76,4 +76,4 @@ "@convertcom/js-sdk-logger": ">=2.1.2", "@convertcom/js-sdk-types": ">=3.11.0" } -} \ No newline at end of file +} diff --git a/packages/js-sdk/package.json b/packages/js-sdk/package.json index 9d730582..fc23609b 100644 --- a/packages/js-sdk/package.json +++ b/packages/js-sdk/package.json @@ -99,4 +99,4 @@ "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} \ No newline at end of file +} diff --git a/packages/logger/package.json b/packages/logger/package.json index f502921f..646130d8 100644 --- a/packages/logger/package.json +++ b/packages/logger/package.json @@ -70,4 +70,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} \ No newline at end of file +} diff --git a/packages/rules/package.json b/packages/rules/package.json index 11421cce..a3f192cb 100644 --- a/packages/rules/package.json +++ b/packages/rules/package.json @@ -76,4 +76,4 @@ "@convertcom/js-sdk-types": ">=3.11.0", "@convertcom/js-sdk-utils": ">=2.2.3" } -} \ No newline at end of file +} diff --git a/packages/segments/package.json b/packages/segments/package.json index 50966935..3b4ce56b 100644 --- a/packages/segments/package.json +++ b/packages/segments/package.json @@ -77,4 +77,4 @@ "@convertcom/js-sdk-rules": ">=2.1.4", "@convertcom/js-sdk-types": ">=3.11.0" } -} \ No newline at end of file +} diff --git a/packages/types/package.json b/packages/types/package.json index e260c057..eaad2997 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -53,4 +53,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} \ No newline at end of file +} diff --git a/packages/utils/package.json b/packages/utils/package.json index 4303f081..e346cb46 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -74,4 +74,4 @@ "peerDependencies": { "@convertcom/js-sdk-enums": ">=2.3.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index cc4cd58d..809a61b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 8 + version: 9 cacheKey: 10c0 "@alloc/quick-lru@npm:^5.2.0": @@ -3300,7 +3300,7 @@ __metadata: "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-event": ">=2.1.3" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" "@convertcom/js-sdk-utils": ">=2.2.3" languageName: unknown linkType: soft @@ -3348,7 +3348,7 @@ __metadata: peerDependencies: "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" "@convertcom/js-sdk-utils": ">=2.2.3" languageName: unknown linkType: soft @@ -3426,8 +3426,8 @@ __metadata: "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-event": ">=2.1.3" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-rules": ">=2.1.3" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-rules": ">=2.1.4" + "@convertcom/js-sdk-types": ">=3.11.0" "@convertcom/js-sdk-utils": ">=2.2.3" languageName: unknown linkType: soft @@ -3551,7 +3551,7 @@ __metadata: peerDependencies: "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" languageName: unknown linkType: soft @@ -3599,7 +3599,7 @@ __metadata: "@convertcom/js-sdk-data": ">=3.3.3" "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" languageName: unknown linkType: soft @@ -3688,7 +3688,7 @@ __metadata: peerDependencies: "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" "@convertcom/js-sdk-utils": ">=2.2.3" languageName: unknown linkType: soft @@ -3737,8 +3737,8 @@ __metadata: "@convertcom/js-sdk-data": ">=3.3.3" "@convertcom/js-sdk-enums": ">=2.3.0" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-rules": ">=2.1.3" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-rules": ">=2.1.4" + "@convertcom/js-sdk-types": ">=3.11.0" languageName: unknown linkType: soft @@ -3877,9 +3877,9 @@ __metadata: "@convertcom/js-sdk-event": ">=2.1.3" "@convertcom/js-sdk-experience": ">=2.3.2" "@convertcom/js-sdk-logger": ">=2.1.2" - "@convertcom/js-sdk-rules": ">=2.1.3" + "@convertcom/js-sdk-rules": ">=2.1.4" "@convertcom/js-sdk-segments": ">=2.1.2" - "@convertcom/js-sdk-types": ">=3.9.0" + "@convertcom/js-sdk-types": ">=3.11.0" "@convertcom/js-sdk-utils": ">=2.2.3" languageName: unknown linkType: soft From 1ab9afe6c0a1d2c8aff100b352c8581280bb3465 Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Mon, 18 May 2026 22:20:20 +0300 Subject: [PATCH 08/11] fix(ci): pin Playwright browsers to project's installed version Reorders the QA workflow to install yarn deps before Playwright browsers, and uses `yarn playwright install` instead of `npx`. With `npx` running before `yarn`, node_modules was empty so npx fetched the latest playwright from npm (1.60.0 today) and downloaded chromium binaries for that revision. The job then ran tests against the project's pinned @playwright/test@1.59.1, which expects a different chromium-headless-shell build, hitting "Executable doesn't exist at .../chromium_headless_shell-1217/..." on every browser test. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/qa.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index dcb0225e..e87d5d2e 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -34,10 +34,13 @@ jobs: corepack enable corepack prepare yarn@stable --activate + - name: Install dependencies + run: yarn + - name: Install Playwright browsers run: | cd packages/js-sdk - npx playwright install --with-deps chromium + yarn playwright install --with-deps chromium - name: Runs the SDK QA checks env: @@ -45,7 +48,6 @@ jobs: CONVERT_STAGING_SDK_KEY2: ${{ secrets.CONVERT_STAGING_SDK_KEY2 }} CONVERT_STAGING_SDK_KEY2_SECRET: ${{ secrets.CONVERT_STAGING_SDK_KEY2_SECRET }} run: | - yarn cd packages/js-sdk yarn lint yarn build From c379e1dccde7e095c33e4a17affa6ae1f914c248 Mon Sep 17 00:00:00 2001 From: abbaseya Date: Tue, 19 May 2026 12:56:35 +0000 Subject: [PATCH 09/11] feat: automated TS Serving API update --- packages/types/src/config/types.gen.ts | 1090 +++++++++--------------- 1 file changed, 409 insertions(+), 681 deletions(-) diff --git a/packages/types/src/config/types.gen.ts b/packages/types/src/config/types.gen.ts index b0dfc202..89b32ea9 100644 --- a/packages/types/src/config/types.gen.ts +++ b/packages/types/src/config/types.gen.ts @@ -26,18 +26,10 @@ export type ConfigAudience = { * * **transient** - A transient audience is one that is checked every time the user is being bucketed into the experience * */ -export type ConfigAudienceTypes = 'permanent' | 'transient'; - -/** - * Type of the Audience. Can be one of the following: `permanent`, `transient`. For full-stack projects, `transient` is the only valid option, the rest will be ignored. - * * **permanent** - A permanent audience is one that is checked only at the time the user is being bucketed into the experience - * * **transient** - A transient audience is one that is checked every time the user is being bucketed into the experience - * - */ -export const ConfigAudienceTypes = { - PERMANENT: 'permanent', - TRANSIENT: 'transient' -} as const; +export enum ConfigAudienceTypes { + PERMANENT = 'permanent', + TRANSIENT = 'transient' +} /** * Account billing status @@ -132,19 +124,10 @@ export type SortDirection = { * Defaults to `desc` (newest/highest first) if not specified. * */ -export type sort_direction = 'asc' | 'desc'; - -/** - * The direction for sorting the list results, based on the `sort_by` field. - * - `asc`: Ascending order (e.g., A-Z, 1-10, oldest to newest). - * - `desc`: Descending order (e.g., Z-A, 10-1, newest to oldest). - * Defaults to `desc` (newest/highest first) if not specified. - * - */ -export const sort_direction = { - ASC: 'asc', - DESC: 'desc' -} as const; +export enum sort_direction { + ASC = 'asc', + DESC = 'desc' +} export type OnlyCount = { /** @@ -230,15 +213,10 @@ export type BaseRuleWithVisitorTypeValue = BaseRule & { /** * Type of the visitors */ -export type value = 'new' | 'returning'; - -/** - * Type of the visitors - */ -export const value = { - NEW: 'new', - RETURNING: 'returning' -} as const; +export enum value { + NEW = 'new', + RETURNING = 'returning' +} export type BaseRuleWithExperienceBucketedValue = BaseRule & { /** @@ -285,20 +263,15 @@ export type BaseRuleWithBrowserNameValue = BaseRule & { /** * Browser name used for matching */ -export type value2 = 'chrome' | 'microsoft_ie' | 'firefox' | 'microsoft_edge' | 'mozilla' | 'opera' | 'safari'; - -/** - * Browser name used for matching - */ -export const value2 = { - CHROME: 'chrome', - MICROSOFT_IE: 'microsoft_ie', - FIREFOX: 'firefox', - MICROSOFT_EDGE: 'microsoft_edge', - MOZILLA: 'mozilla', - OPERA: 'opera', - SAFARI: 'safari' -} as const; +export enum value2 { + CHROME = 'chrome', + MICROSOFT_IE = 'microsoft_ie', + FIREFOX = 'firefox', + MICROSOFT_EDGE = 'microsoft_edge', + MOZILLA = 'mozilla', + OPERA = 'opera', + SAFARI = 'safari' +} export type BaseRuleWithOsValue = BaseRule & { /** @@ -310,20 +283,15 @@ export type BaseRuleWithOsValue = BaseRule & { /** * Operating System name used for matching */ -export type value3 = 'android' | 'iphone' | 'ipod' | 'ipad' | 'windows' | 'macos' | 'linux'; - -/** - * Operating System name used for matching - */ -export const value3 = { - ANDROID: 'android', - IPHONE: 'iphone', - IPOD: 'ipod', - IPAD: 'ipad', - WINDOWS: 'windows', - MACOS: 'macos', - LINUX: 'linux' -} as const; +export enum value3 { + ANDROID = 'android', + IPHONE = 'iphone', + IPOD = 'ipod', + IPAD = 'ipad', + WINDOWS = 'windows', + MACOS = 'macos', + LINUX = 'linux' +} export type BaseRuleWithWeatherConditionValue = BaseRule & { /** @@ -355,38 +323,33 @@ export type BaseRuleWithWeatherConditionValue = BaseRule & { /** * Standardized weather condition strings used for targeting. */ -export type WeatherConditions = 'Blizzard' | 'Blowing snow' | 'Cloudy' | 'Fog' | 'Freezing drizzle' | 'Freezing fog' | 'Heavy freezing drizzle' | 'Heavy rain' | 'Heavy rain at times' | 'Light drizzle' | 'Light freezing rain' | 'Light rain' | 'Mist' | 'Moderate rain' | 'Moderate rain at times' | 'Overcast' | 'Partly cloudy' | 'Patchy freezing drizzle possible' | 'Patchy light drizzle' | 'Patchy light rain' | 'Patchy rain possible' | 'Patchy sleet possible' | 'Patchy snow possible' | 'Sunny' | 'Thundery outbreaks possible'; - -/** - * Standardized weather condition strings used for targeting. - */ -export const WeatherConditions = { - BLIZZARD: 'Blizzard', - BLOWING_SNOW: 'Blowing snow', - CLOUDY: 'Cloudy', - FOG: 'Fog', - FREEZING_DRIZZLE: 'Freezing drizzle', - FREEZING_FOG: 'Freezing fog', - HEAVY_FREEZING_DRIZZLE: 'Heavy freezing drizzle', - HEAVY_RAIN: 'Heavy rain', - HEAVY_RAIN_AT_TIMES: 'Heavy rain at times', - LIGHT_DRIZZLE: 'Light drizzle', - LIGHT_FREEZING_RAIN: 'Light freezing rain', - LIGHT_RAIN: 'Light rain', - MIST: 'Mist', - MODERATE_RAIN: 'Moderate rain', - MODERATE_RAIN_AT_TIMES: 'Moderate rain at times', - OVERCAST: 'Overcast', - PARTLY_CLOUDY: 'Partly cloudy', - PATCHY_FREEZING_DRIZZLE_POSSIBLE: 'Patchy freezing drizzle possible', - PATCHY_LIGHT_DRIZZLE: 'Patchy light drizzle', - PATCHY_LIGHT_RAIN: 'Patchy light rain', - PATCHY_RAIN_POSSIBLE: 'Patchy rain possible', - PATCHY_SLEET_POSSIBLE: 'Patchy sleet possible', - PATCHY_SNOW_POSSIBLE: 'Patchy snow possible', - SUNNY: 'Sunny', - THUNDERY_OUTBREAKS_POSSIBLE: 'Thundery outbreaks possible' -} as const; +export enum WeatherConditions { + BLIZZARD = 'Blizzard', + BLOWING_SNOW = 'Blowing snow', + CLOUDY = 'Cloudy', + FOG = 'Fog', + FREEZING_DRIZZLE = 'Freezing drizzle', + FREEZING_FOG = 'Freezing fog', + HEAVY_FREEZING_DRIZZLE = 'Heavy freezing drizzle', + HEAVY_RAIN = 'Heavy rain', + HEAVY_RAIN_AT_TIMES = 'Heavy rain at times', + LIGHT_DRIZZLE = 'Light drizzle', + LIGHT_FREEZING_RAIN = 'Light freezing rain', + LIGHT_RAIN = 'Light rain', + MIST = 'Mist', + MODERATE_RAIN = 'Moderate rain', + MODERATE_RAIN_AT_TIMES = 'Moderate rain at times', + OVERCAST = 'Overcast', + PARTLY_CLOUDY = 'Partly cloudy', + PATCHY_FREEZING_DRIZZLE_POSSIBLE = 'Patchy freezing drizzle possible', + PATCHY_LIGHT_DRIZZLE = 'Patchy light drizzle', + PATCHY_LIGHT_RAIN = 'Patchy light rain', + PATCHY_RAIN_POSSIBLE = 'Patchy rain possible', + PATCHY_SLEET_POSSIBLE = 'Patchy sleet possible', + PATCHY_SNOW_POSSIBLE = 'Patchy snow possible', + SUNNY = 'Sunny', + THUNDERY_OUTBREAKS_POSSIBLE = 'Thundery outbreaks possible' +} export type BaseMatch = { /** @@ -397,159 +360,119 @@ export type BaseMatch = { negated?: boolean; }; -export type TextMatchRulesTypes = 'url' | 'url_with_query' | 'query_string' | 'campaign' | 'keyword' | 'medium' | 'source_name' | 'city' | 'region' | 'browser_version' | 'user_agent' | 'page_tag_page_type' | 'page_tag_category_id' | 'page_tag_category_name' | 'page_tag_product_sku' | 'page_tag_product_name' | 'page_tag_customer_id' | 'page_tag_custom_1' | 'page_tag_custom_2' | 'page_tag_custom_3' | 'page_tag_custom_4' | 'visitor_id'; - -export const TextMatchRulesTypes = { - URL: 'url', - URL_WITH_QUERY: 'url_with_query', - QUERY_STRING: 'query_string', - CAMPAIGN: 'campaign', - KEYWORD: 'keyword', - MEDIUM: 'medium', - SOURCE_NAME: 'source_name', - CITY: 'city', - REGION: 'region', - BROWSER_VERSION: 'browser_version', - USER_AGENT: 'user_agent', - PAGE_TAG_PAGE_TYPE: 'page_tag_page_type', - PAGE_TAG_CATEGORY_ID: 'page_tag_category_id', - PAGE_TAG_CATEGORY_NAME: 'page_tag_category_name', - PAGE_TAG_PRODUCT_SKU: 'page_tag_product_sku', - PAGE_TAG_PRODUCT_NAME: 'page_tag_product_name', - PAGE_TAG_CUSTOMER_ID: 'page_tag_customer_id', - PAGE_TAG_CUSTOM_1: 'page_tag_custom_1', - PAGE_TAG_CUSTOM_2: 'page_tag_custom_2', - PAGE_TAG_CUSTOM_3: 'page_tag_custom_3', - PAGE_TAG_CUSTOM_4: 'page_tag_custom_4', - VISITOR_ID: 'visitor_id' -} as const; - -export type NumericMatchRulesTypes = 'avg_time_page' | 'days_since_last_visit' | 'pages_visited_count' | 'visit_duration' | 'visits_count' | 'page_tag_product_price'; - -export const NumericMatchRulesTypes = { - AVG_TIME_PAGE: 'avg_time_page', - DAYS_SINCE_LAST_VISIT: 'days_since_last_visit', - PAGES_VISITED_COUNT: 'pages_visited_count', - VISIT_DURATION: 'visit_duration', - VISITS_COUNT: 'visits_count', - PAGE_TAG_PRODUCT_PRICE: 'page_tag_product_price' -} as const; - -export type BoolMatchRulesTypes = 'bucketed_into_experience' | 'is_desktop' | 'is_mobile' | 'is_tablet'; - -export const BoolMatchRulesTypes = { - BUCKETED_INTO_EXPERIENCE: 'bucketed_into_experience', - IS_DESKTOP: 'is_desktop', - IS_MOBILE: 'is_mobile', - IS_TABLET: 'is_tablet' -} as const; - -export type GenericTextKeyValueMatchRulesTypes = 'generic_text_key_value'; - -export const GenericTextKeyValueMatchRulesTypes = { - GENERIC_TEXT_KEY_VALUE: 'generic_text_key_value' -} as const; - -export type GenericNumericKeyValueMatchRulesTypes = 'generic_numeric_key_value'; - -export const GenericNumericKeyValueMatchRulesTypes = { - GENERIC_NUMERIC_KEY_VALUE: 'generic_numeric_key_value' -} as const; - -export type GenericBoolKeyValueMatchRulesTypes = 'generic_bool_key_value'; - -export const GenericBoolKeyValueMatchRulesTypes = { - GENERIC_BOOL_KEY_VALUE: 'generic_bool_key_value' -} as const; - -export type VisitorDataExistsMatchRulesTypes = 'visitor_data_exists'; - -export const VisitorDataExistsMatchRulesTypes = { - VISITOR_DATA_EXISTS: 'visitor_data_exists' -} as const; - -export type JsConditionMatchRulesTypes = 'js_condition'; - -export const JsConditionMatchRulesTypes = { - JS_CONDITION: 'js_condition' -} as const; +export enum TextMatchRulesTypes { + URL = 'url', + URL_WITH_QUERY = 'url_with_query', + QUERY_STRING = 'query_string', + CAMPAIGN = 'campaign', + KEYWORD = 'keyword', + MEDIUM = 'medium', + SOURCE_NAME = 'source_name', + CITY = 'city', + REGION = 'region', + BROWSER_VERSION = 'browser_version', + USER_AGENT = 'user_agent', + PAGE_TAG_PAGE_TYPE = 'page_tag_page_type', + PAGE_TAG_CATEGORY_ID = 'page_tag_category_id', + PAGE_TAG_CATEGORY_NAME = 'page_tag_category_name', + PAGE_TAG_PRODUCT_SKU = 'page_tag_product_sku', + PAGE_TAG_PRODUCT_NAME = 'page_tag_product_name', + PAGE_TAG_CUSTOMER_ID = 'page_tag_customer_id', + PAGE_TAG_CUSTOM_1 = 'page_tag_custom_1', + PAGE_TAG_CUSTOM_2 = 'page_tag_custom_2', + PAGE_TAG_CUSTOM_3 = 'page_tag_custom_3', + PAGE_TAG_CUSTOM_4 = 'page_tag_custom_4', + VISITOR_ID = 'visitor_id' +} + +export enum NumericMatchRulesTypes { + AVG_TIME_PAGE = 'avg_time_page', + DAYS_SINCE_LAST_VISIT = 'days_since_last_visit', + PAGES_VISITED_COUNT = 'pages_visited_count', + VISIT_DURATION = 'visit_duration', + VISITS_COUNT = 'visits_count', + PAGE_TAG_PRODUCT_PRICE = 'page_tag_product_price' +} + +export enum BoolMatchRulesTypes { + BUCKETED_INTO_EXPERIENCE = 'bucketed_into_experience', + IS_DESKTOP = 'is_desktop', + IS_MOBILE = 'is_mobile', + IS_TABLET = 'is_tablet' +} + +export enum GenericTextKeyValueMatchRulesTypes { + GENERIC_TEXT_KEY_VALUE = 'generic_text_key_value' +} + +export enum GenericNumericKeyValueMatchRulesTypes { + GENERIC_NUMERIC_KEY_VALUE = 'generic_numeric_key_value' +} + +export enum GenericBoolKeyValueMatchRulesTypes { + GENERIC_BOOL_KEY_VALUE = 'generic_bool_key_value' +} + +export enum VisitorDataExistsMatchRulesTypes { + VISITOR_DATA_EXISTS = 'visitor_data_exists' +} + +export enum JsConditionMatchRulesTypes { + JS_CONDITION = 'js_condition' +} export type KeyValueMatchRulesTypes = GenericTextKeyValueMatchRulesTypes & GenericNumericKeyValueMatchRulesTypes & GenericBoolKeyValueMatchRulesTypes; -export type CookieMatchRulesTypes = 'cookie'; - -export const CookieMatchRulesTypes = { - COOKIE: 'cookie' -} as const; - -export type CountryMatchRulesTypes = 'country'; - -export const CountryMatchRulesTypes = { - COUNTRY: 'country' -} as const; +export enum CookieMatchRulesTypes { + COOKIE = 'cookie' +} -export type VisitorTypeMatchRulesTypes = 'visitor_type'; +export enum CountryMatchRulesTypes { + COUNTRY = 'country' +} -export const VisitorTypeMatchRulesTypes = { - VISITOR_TYPE: 'visitor_type' -} as const; +export enum VisitorTypeMatchRulesTypes { + VISITOR_TYPE = 'visitor_type' +} -export type LanguageMatchRulesTypes = 'language'; +export enum LanguageMatchRulesTypes { + LANGUAGE = 'language' +} -export const LanguageMatchRulesTypes = { - LANGUAGE: 'language' -} as const; +export enum GoalTriggeredMatchRulesTypes { + GOAL_TRIGGERED = 'goal_triggered' +} -export type GoalTriggeredMatchRulesTypes = 'goal_triggered'; +export enum SegmentBucketedMatchRulesTypes { + BUCKETED_INTO_SEGMENT = 'bucketed_into_segment' +} -export const GoalTriggeredMatchRulesTypes = { - GOAL_TRIGGERED: 'goal_triggered' -} as const; +export enum DayOfWeekMatchRulesTypes { + LOCAL_TIME_DAY_OF_WEEK = 'local_time_day_of_week', + PROJECT_TIME_DAY_OF_WEEK = 'project_time_day_of_week' +} -export type SegmentBucketedMatchRulesTypes = 'bucketed_into_segment'; +export enum HourOfDayMatchRulesTypes { + LOCAL_TIME_HOUR_OF_DAY = 'local_time_hour_of_day', + PROJECT_TIME_HOUR_OF_DAY = 'project_time_hour_of_day' +} -export const SegmentBucketedMatchRulesTypes = { - BUCKETED_INTO_SEGMENT: 'bucketed_into_segment' -} as const; +export enum MinuteOfHourMatchRulesTypes { + LOCAL_TIME_MINUTE_OF_HOUR = 'local_time_minute_of_hour', + PROJECT_TIME_MINUTE_OF_HOUR = 'project_time_minute_of_hour' +} -export type DayOfWeekMatchRulesTypes = 'local_time_day_of_week' | 'project_time_day_of_week'; +export enum BrowserNameMatchRulesTypes { + BROWSER_NAME = 'browser_name' +} -export const DayOfWeekMatchRulesTypes = { - LOCAL_TIME_DAY_OF_WEEK: 'local_time_day_of_week', - PROJECT_TIME_DAY_OF_WEEK: 'project_time_day_of_week' -} as const; - -export type HourOfDayMatchRulesTypes = 'local_time_hour_of_day' | 'project_time_hour_of_day'; - -export const HourOfDayMatchRulesTypes = { - LOCAL_TIME_HOUR_OF_DAY: 'local_time_hour_of_day', - PROJECT_TIME_HOUR_OF_DAY: 'project_time_hour_of_day' -} as const; +export enum OsMatchRulesTypes { + OS = 'os' +} -export type MinuteOfHourMatchRulesTypes = 'local_time_minute_of_hour' | 'project_time_minute_of_hour'; - -export const MinuteOfHourMatchRulesTypes = { - LOCAL_TIME_MINUTE_OF_HOUR: 'local_time_minute_of_hour', - PROJECT_TIME_MINUTE_OF_HOUR: 'project_time_minute_of_hour' -} as const; - -export type BrowserNameMatchRulesTypes = 'browser_name'; - -export const BrowserNameMatchRulesTypes = { - BROWSER_NAME: 'browser_name' -} as const; - -export type OsMatchRulesTypes = 'os'; - -export const OsMatchRulesTypes = { - OS: 'os' -} as const; - -export type WeatherConditionMatchRulesTypes = 'weather_condition'; - -export const WeatherConditionMatchRulesTypes = { - WEATHER_CONDITION: 'weather_condition' -} as const; +export enum WeatherConditionMatchRulesTypes { + WEATHER_CONDITION = 'weather_condition' +} export type RulesTypes = TextMatchRulesTypes & NumericMatchRulesTypes & BoolMatchRulesTypes & KeyValueMatchRulesTypes & VisitorDataExistsMatchRulesTypes & CookieMatchRulesTypes & CountryMatchRulesTypes & VisitorTypeMatchRulesTypes & LanguageMatchRulesTypes & GoalTriggeredMatchRulesTypes & SegmentBucketedMatchRulesTypes & DayOfWeekMatchRulesTypes & HourOfDayMatchRulesTypes & MinuteOfHourMatchRulesTypes & BrowserNameMatchRulesTypes & OsMatchRulesTypes & WeatherConditionMatchRulesTypes; @@ -724,53 +647,41 @@ export type RuleElement = GenericTextMatchRule | GenericNumericMatchRule | Gener export type RuleElementAudience = GenericTextMatchRule | GenericNumericMatchRule | GenericBoolMatchRule | GenericTextKeyValueMatchRule | GenericNumericKeyValueMatchRule | GenericBoolKeyValueMatchRule | CookieMatchRule | CountryMatchRule | LanguageMatchRule | GoalTriggeredMatchRule | SegmentBucketedMatchRule | DayOfWeekMatchRule | HourOfDayMatchRule | MinuteOfHourMatchRule | BrowserNameMatchRule | OsMatchRule | WeatherConditionMatchRule | VisitorTypeMatchRule | JsConditionMatchRule | VisitorDataExistsMatchRule; -export type TextMatchingOptions = 'matches' | 'regexMatches' | 'contains' | 'endsWith' | 'startsWith'; - -export const TextMatchingOptions = { - MATCHES: 'matches', - REGEX_MATCHES: 'regexMatches', - CONTAINS: 'contains', - ENDS_WITH: 'endsWith', - STARTS_WITH: 'startsWith' -} as const; - -export type CookieMatchingOptions = 'matches' | 'regexMatches' | 'contains' | 'endsWith' | 'startsWith' | 'exists' | 'doesNotExist'; - -export const CookieMatchingOptions = { - MATCHES: 'matches', - REGEX_MATCHES: 'regexMatches', - CONTAINS: 'contains', - ENDS_WITH: 'endsWith', - STARTS_WITH: 'startsWith', - EXISTS: 'exists', - DOES_NOT_EXIST: 'doesNotExist' -} as const; - -export type NumericMatchingOptions = 'equalsNumber' | 'less' | 'lessEqual'; - -export const NumericMatchingOptions = { - EQUALS_NUMBER: 'equalsNumber', - LESS: 'less', - LESS_EQUAL: 'lessEqual' -} as const; - -export type ChoiceMatchingOptions = 'equals'; - -export const ChoiceMatchingOptions = { - EQUALS: 'equals' -} as const; - -export type ChoiceContainsOptions = 'contains'; - -export const ChoiceContainsOptions = { - CONTAINS: 'contains' -} as const; - -export type SetMatchingOptions = 'isIn'; - -export const SetMatchingOptions = { - IS_IN: 'isIn' -} as const; +export enum TextMatchingOptions { + MATCHES = 'matches', + REGEX_MATCHES = 'regexMatches', + CONTAINS = 'contains', + ENDS_WITH = 'endsWith', + STARTS_WITH = 'startsWith' +} + +export enum CookieMatchingOptions { + MATCHES = 'matches', + REGEX_MATCHES = 'regexMatches', + CONTAINS = 'contains', + ENDS_WITH = 'endsWith', + STARTS_WITH = 'startsWith', + EXISTS = 'exists', + DOES_NOT_EXIST = 'doesNotExist' +} + +export enum NumericMatchingOptions { + EQUALS_NUMBER = 'equalsNumber', + LESS = 'less', + LESS_EQUAL = 'lessEqual' +} + +export enum ChoiceMatchingOptions { + EQUALS = 'equals' +} + +export enum ChoiceContainsOptions { + CONTAINS = 'contains' +} + +export enum SetMatchingOptions { + IS_IN = 'isIn' +} /** * Defines the logical structure for combining multiple rule conditions. It uses a nested OR -> AND -> OR_WHEN structure. @@ -924,11 +835,9 @@ export type IntegrationGA3 = { property_UA?: (string) | null; }; -export type type = 'ga3'; - -export const type = { - GA3: 'ga3' -} as const; +export enum type { + GA3 = 'ga3' +} export type IntegrationGA4Base = { type?: 'ga4'; @@ -938,11 +847,9 @@ export type IntegrationGA4Base = { measurementId?: string; }; -export type type2 = 'ga4'; - -export const type2 = { - GA4: 'ga4' -} as const; +export enum type2 { + GA4 = 'ga4' +} export type IntegrationGA4 = IntegrationGA4Base & { /** @@ -958,19 +865,10 @@ export type IntegrationGA4 = IntegrationGA4Base & { * Default is typically 'any' (OR). * */ -export type GenericListMatchingOptions = 'any' | 'all'; - -/** - * Defines how multiple conditions within a list (e.g., multiple audiences or locations linked to an experience) are logically combined: - * - `any`: The overall condition is met if *at least one* item in the list matches (logical OR). - * - `all`: The overall condition is met only if *all* items in the list match (logical AND). - * Default is typically 'any' (OR). - * - */ -export const GenericListMatchingOptions = { - ANY: 'any', - ALL: 'all' -} as const; +export enum GenericListMatchingOptions { + ANY = 'any', + ALL = 'all' +} export type VisitorInsightsBase = { /** @@ -996,21 +894,14 @@ export type VisitorInsightsBase = { * Higher values collect data from a larger share of traffic and consume allocation faster. * */ -export type sampling_rate = 5 | 10 | 20 | 30 | 40 | 50; - -/** - * The percentage of visitors included in sampling for Convert Signals session recordings and Heatmaps for this project. - * Higher values collect data from a larger share of traffic and consume allocation faster. - * - */ -export const sampling_rate = { - '_5': 5, - '_10': 10, - '_20': 20, - '_30': 30, - '_40': 40, - '_50': 50 -} as const; +export enum sampling_rate { + '_5' = 5, + '_10' = 10, + '_20' = 20, + '_30' = 30, + '_40' = 40, + '_50' = 50 +} /** * The method used for detecting and handling order outliers in revenue or product count tracking: @@ -1019,20 +910,11 @@ export const sampling_rate = { * - `percentile`: Orders falling below a lower percentile or above an upper percentile are capped at the values corresponding to those percentiles. * */ -export type NumericOutlierTypes = 'none' | 'min_max' | 'percentile'; - -/** - * The method used for detecting and handling order outliers in revenue or product count tracking: - * - `none`: No outlier detection is applied. - * - `min_max`: Orders with values below a specified minimum or above a specified maximum are capped at those boundaries. - * - `percentile`: Orders falling below a lower percentile or above an upper percentile are capped at the values corresponding to those percentiles. - * - */ -export const NumericOutlierTypes = { - NONE: 'none', - MIN_MAX: 'min_max', - PERCENTILE: 'percentile' -} as const; +export enum NumericOutlierTypes { + NONE = 'none', + MIN_MAX = 'min_max', + PERCENTILE = 'percentile' +} export type NumericOutlierBase = { detection_type: NumericOutlierTypes; @@ -1042,11 +924,9 @@ export type NumericOutlierNone = NumericOutlierBase & { detection_type?: 'none'; }; -export type detection_type = 'none'; - -export const detection_type = { - NONE: 'none' -} as const; +export enum detection_type { + NONE = 'none' +} export type NumericOutlierMinMax = NumericOutlierBase & { detection_type?: 'min_max'; @@ -1060,11 +940,9 @@ export type NumericOutlierMinMax = NumericOutlierBase & { max?: number; }; -export type detection_type2 = 'min_max'; - -export const detection_type2 = { - MIN_MAX: 'min_max' -} as const; +export enum detection_type2 { + MIN_MAX = 'min_max' +} export type NumericOutlierPercentile = NumericOutlierBase & { detection_type?: 'percentile'; @@ -1072,11 +950,9 @@ export type NumericOutlierPercentile = NumericOutlierBase & { max?: (unknown & Percentiles); }; -export type detection_type3 = 'percentile'; - -export const detection_type3 = { - PERCENTILE: 'percentile' -} as const; +export enum detection_type3 { + PERCENTILE = 'percentile' +} export type NumericOutlier = NumericOutlierNone | NumericOutlierMinMax | NumericOutlierPercentile; @@ -1085,24 +961,17 @@ export type NumericOutlier = NumericOutlierNone | NumericOutlierMinMax | Numeric * For example, a `min` of 5 and `max` of 95 means orders in the bottom 5% and top 5% of values are considered outliers and capped. * */ -export type Percentiles = 1 | 5 | 10 | 25 | 50 | 75 | 90 | 95 | 99; - -/** - * Standard percentile values used for outlier detection thresholds. - * For example, a `min` of 5 and `max` of 95 means orders in the bottom 5% and top 5% of values are considered outliers and capped. - * - */ -export const Percentiles = { - '_1': 1, - '_5': 5, - '_10': 10, - '_25': 25, - '_50': 50, - '_75': 75, - '_90': 90, - '_95': 95, - '_99': 99 -} as const; +export enum Percentiles { + '_1' = 1, + '_5' = 5, + '_10' = 10, + '_25' = 25, + '_50' = 50, + '_75' = 75, + '_90' = 90, + '_95' = 95, + '_99' = 99 +} export type TimeRange = { /** @@ -1226,16 +1095,14 @@ export type ExperienceChangeBase = { }; }; -export type type3 = 'richStructure' | 'customCode' | 'defaultCode' | 'defaultCodeMultipage' | 'defaultRedirect' | 'fullStackFeature'; - -export const type3 = { - RICH_STRUCTURE: 'richStructure', - CUSTOM_CODE: 'customCode', - DEFAULT_CODE: 'defaultCode', - DEFAULT_CODE_MULTIPAGE: 'defaultCodeMultipage', - DEFAULT_REDIRECT: 'defaultRedirect', - FULL_STACK_FEATURE: 'fullStackFeature' -} as const; +export enum type3 { + RICH_STRUCTURE = 'richStructure', + CUSTOM_CODE = 'customCode', + DEFAULT_CODE = 'defaultCode', + DEFAULT_CODE_MULTIPAGE = 'defaultCodeMultipage', + DEFAULT_REDIRECT = 'defaultRedirect', + FULL_STACK_FEATURE = 'fullStackFeature' +} /** * Represents the unique identifier of an existing change within an experience variation. Used when updating or referencing a specific change. @@ -1306,11 +1173,9 @@ export type ExperienceChangeDefaultCodeDataBase = ExperienceChangeBase & { }; }; -export type type4 = 'defaultCode'; - -export const type4 = { - DEFAULT_CODE: 'defaultCode' -} as const; +export enum type4 { + DEFAULT_CODE = 'defaultCode' +} /** * Represents a 'defaultCode' type change, including its system-assigned ID. @@ -1369,11 +1234,9 @@ export type ExperienceChangeDefaultRedirectDataBase = ExperienceChangeBase & { }; }; -export type type5 = 'defaultRedirect'; - -export const type5 = { - DEFAULT_REDIRECT: 'defaultRedirect' -} as const; +export enum type5 { + DEFAULT_REDIRECT = 'defaultRedirect' +} /** * Represents a 'defaultRedirect' type change, including its system-assigned ID. @@ -1436,11 +1299,9 @@ export type ExperienceChangeDefaultCodeMultipageDataBase = ExperienceChangeBase }; }; -export type type6 = 'defaultCodeMultipage'; - -export const type6 = { - DEFAULT_CODE_MULTIPAGE: 'defaultCodeMultipage' -} as const; +export enum type6 { + DEFAULT_CODE_MULTIPAGE = 'defaultCodeMultipage' +} /** * Represents a 'defaultCodeMultipage' type change, including its system-assigned ID. @@ -1503,11 +1364,9 @@ export type ExperienceChangeRichStructureDataBase = ExperienceChangeBase & { }; }; -export type type7 = 'richStructure'; - -export const type7 = { - RICH_STRUCTURE: 'richStructure' -} as const; +export enum type7 { + RICH_STRUCTURE = 'richStructure' +} /** * Represents a 'richStructure' type change, including its system-assigned ID. @@ -1566,11 +1425,9 @@ export type ExperienceChangeCustomCodeDataBase = ExperienceChangeBase & { }; }; -export type type8 = 'customCode'; - -export const type8 = { - CUSTOM_CODE: 'customCode' -} as const; +export enum type8 { + CUSTOM_CODE = 'customCode' +} /** * Represents a 'customCode' type change, including its system-assigned ID. @@ -1627,11 +1484,9 @@ export type ExperienceChangeFullStackFeatureBase = ExperienceChangeBase & { }; }; -export type type9 = 'fullStackFeature'; - -export const type9 = { - FULL_STACK_FEATURE: 'fullStackFeature' -} as const; +export enum type9 { + FULL_STACK_FEATURE = 'fullStackFeature' +} /** * Represents a 'fullStackFeature' type change, including its system-assigned ID. @@ -1674,35 +1529,27 @@ export type UpdateExperienceChangeRequestData = ExperienceChangeAdd; * Knowledge Base has many articles on integrations, e.g., "Integrate Convert Experiences with Google Analytics", "Hotjar Integration". * */ -export type IntegrationProvider = 'baidu' | 'clicktale' | 'clicky' | 'cnzz' | 'crazyegg' | 'econda' | 'eulerian' | 'google_analytics' | 'gosquared' | 'heapanalytics' | 'hotjar' | 'microsoft_clarity' | 'mixpanel' | 'mouseflow' | 'piwik' | 'segmentio' | 'sitecatalyst' | 'woopra' | 'ysance'; - -/** - * Identifies the third-party analytics, heatmap, or data platform with which Convert Experiences is integrated for this specific experience. - * This allows experiment data (like experience ID and variation ID/name) to be sent to the selected provider. - * Knowledge Base has many articles on integrations, e.g., "Integrate Convert Experiences with Google Analytics", "Hotjar Integration". - * - */ -export const IntegrationProvider = { - BAIDU: 'baidu', - CLICKTALE: 'clicktale', - CLICKY: 'clicky', - CNZZ: 'cnzz', - CRAZYEGG: 'crazyegg', - ECONDA: 'econda', - EULERIAN: 'eulerian', - GOOGLE_ANALYTICS: 'google_analytics', - GOSQUARED: 'gosquared', - HEAPANALYTICS: 'heapanalytics', - HOTJAR: 'hotjar', - MICROSOFT_CLARITY: 'microsoft_clarity', - MIXPANEL: 'mixpanel', - MOUSEFLOW: 'mouseflow', - PIWIK: 'piwik', - SEGMENTIO: 'segmentio', - SITECATALYST: 'sitecatalyst', - WOOPRA: 'woopra', - YSANCE: 'ysance' -} as const; +export enum IntegrationProvider { + BAIDU = 'baidu', + CLICKTALE = 'clicktale', + CLICKY = 'clicky', + CNZZ = 'cnzz', + CRAZYEGG = 'crazyegg', + ECONDA = 'econda', + EULERIAN = 'eulerian', + GOOGLE_ANALYTICS = 'google_analytics', + GOSQUARED = 'gosquared', + HEAPANALYTICS = 'heapanalytics', + HOTJAR = 'hotjar', + MICROSOFT_CLARITY = 'microsoft_clarity', + MIXPANEL = 'mixpanel', + MOUSEFLOW = 'mouseflow', + PIWIK = 'piwik', + SEGMENTIO = 'segmentio', + SITECATALYST = 'sitecatalyst', + WOOPRA = 'woopra', + YSANCE = 'ysance' +} export type ExperienceIntegrationBase = { provider: IntegrationProvider; @@ -1974,39 +1821,32 @@ export type ExperienceVariationConfig = { changes?: Array; }; -export type ExperienceStatuses = 'draft' | 'active' | 'paused' | 'completed' | 'scheduled'; - -export const ExperienceStatuses = { - DRAFT: 'draft', - ACTIVE: 'active', - PAUSED: 'paused', - COMPLETED: 'completed', - SCHEDULED: 'scheduled' -} as const; +export enum ExperienceStatuses { + DRAFT = 'draft', + ACTIVE = 'active', + PAUSED = 'paused', + COMPLETED = 'completed', + SCHEDULED = 'scheduled' +} -export type ExperienceTypes = 'a/b' | 'a/a' | 'mvt' | 'split_url' | 'multipage' | 'deploy'; - -export const ExperienceTypes = { - A_B: 'a/b', - A_A: 'a/a', - MVT: 'mvt', - SPLIT_URL: 'split_url', - MULTIPAGE: 'multipage', - DEPLOY: 'deploy' -} as const; - -/** - * Variation status - */ -export type VariationStatuses = 'stopped' | 'running'; +export enum ExperienceTypes { + A_B = 'a/b', + A_A = 'a/a', + MVT = 'mvt', + SPLIT_URL = 'split_url', + MULTIPAGE = 'multipage', + DEPLOY = 'deploy', + A_B_FULLSTACK = 'a/b_fullstack', + FEATURE_ROLLOUT = 'feature_rollout' +} /** * Variation status */ -export const VariationStatuses = { - STOPPED: 'stopped', - RUNNING: 'running' -} as const; +export enum VariationStatuses { + STOPPED = 'stopped', + RUNNING = 'running' +} export type ExperienceIntegrationGAServing = ExperienceIntegrationGA3 | ExperienceIntegrationGA4Base; @@ -2049,18 +1889,13 @@ export type FeatureVariableItemData = { /** * A variable's type */ -export type type10 = 'boolean' | 'float' | 'json' | 'integer' | 'string'; - -/** - * A variable's type - */ -export const type10 = { - BOOLEAN: 'boolean', - FLOAT: 'float', - JSON: 'json', - INTEGER: 'integer', - STRING: 'string' -} as const; +export enum type10 { + BOOLEAN = 'boolean', + FLOAT = 'float', + JSON = 'json', + INTEGER = 'integer', + STRING = 'string' +} /** * Goal item to be tracked inside a project @@ -2092,89 +1927,73 @@ export type DomInteractionGoal = ConfigGoalBase & { settings?: DomInteractionGoalSettings; }; -export type type11 = 'dom_interaction'; - -export const type11 = { - DOM_INTERACTION: 'dom_interaction' -} as const; +export enum type11 { + DOM_INTERACTION = 'dom_interaction' +} export type ScrollPercentageGoal = ConfigGoalBase & { type?: 'scroll_percentage'; settings?: ScrollPercentageGoalSettings; }; -export type type12 = 'scroll_percentage'; - -export const type12 = { - SCROLL_PERCENTAGE: 'scroll_percentage' -} as const; +export enum type12 { + SCROLL_PERCENTAGE = 'scroll_percentage' +} export type RevenueGoal = ConfigGoalBase & { type?: 'revenue'; settings?: RevenueGoalSettings; }; -export type type13 = 'revenue'; - -export const type13 = { - REVENUE: 'revenue' -} as const; +export enum type13 { + REVENUE = 'revenue' +} export type NoSettingsGoal = ConfigGoalBase & { type?: 'advanced' | 'visits_page' | 'code_trigger'; }; -export type type14 = 'advanced' | 'visits_page' | 'code_trigger'; - -export const type14 = { - ADVANCED: 'advanced', - VISITS_PAGE: 'visits_page', - CODE_TRIGGER: 'code_trigger' -} as const; +export enum type14 { + ADVANCED = 'advanced', + VISITS_PAGE = 'visits_page', + CODE_TRIGGER = 'code_trigger' +} export type GaGoal = ConfigGoalBase & { type?: 'ga_import'; settings?: GaGoalSettings; }; -export type type15 = 'ga_import'; - -export const type15 = { - GA_IMPORT: 'ga_import' -} as const; +export enum type15 { + GA_IMPORT = 'ga_import' +} export type SubmitsFormGoal = ConfigGoalBase & { type?: 'submits_form'; settings?: SubmitsFormGoalSettings; }; -export type type16 = 'submits_form'; - -export const type16 = { - SUBMITS_FORM: 'submits_form' -} as const; +export enum type16 { + SUBMITS_FORM = 'submits_form' +} export type ClicksLinkGoal = ConfigGoalBase & { type?: 'clicks_link'; settings?: ClicksLinkGoalSettings; }; -export type type17 = 'clicks_link'; - -export const type17 = { - CLICKS_LINK: 'clicks_link' -} as const; +export enum type17 { + CLICKS_LINK = 'clicks_link' +} export type ClicksElementGoal = ConfigGoalBase & { type?: 'clicks_element'; settings?: ClicksElementGoalSettings; }; -export type type18 = 'clicks_element'; - -export const type18 = { - CLICKS_ELEMENT: 'clicks_element' -} as const; +export enum type18 { + CLICKS_ELEMENT = 'clicks_element' +} export type DomInteractionGoalSettings = { /** @@ -2226,20 +2045,10 @@ export type RevenueGoalSettings = { * when on page where this goal is triggered via "triggering_rule" * */ -export type triggering_type = 'manual' | 'ga'; - -/** - * Type of the revenue goal tracking, one of the below. - * * "manual" - goal will be triggered through the given revenue tracking code; - * An empty **triggering_rule** has to be provided as that takes priority over manual triggering - * * "ga" - Convert will attempt to pick revenue from GA revenue tracking code and attach it to this goal, - * when on page where this goal is triggered via "triggering_rule" - * - */ -export const triggering_type = { - MANUAL: 'manual', - GA: 'ga' -} as const; +export enum triggering_type { + MANUAL = 'manual', + GA = 'ga' +} export type SubmitsFormGoalSettings = { /** @@ -2269,18 +2078,13 @@ export type ClicksElementGoalSettings = { /** * Goals type, one of below. */ -export type GoalTypes = 'advanced' | 'dom_interaction' | 'scroll_percentage' | 'code_trigger' | 'revenue'; - -/** - * Goals type, one of below. - */ -export const GoalTypes = { - ADVANCED: 'advanced', - DOM_INTERACTION: 'dom_interaction', - SCROLL_PERCENTAGE: 'scroll_percentage', - CODE_TRIGGER: 'code_trigger', - REVENUE: 'revenue' -} as const; +export enum GoalTypes { + ADVANCED = 'advanced', + DOM_INTERACTION = 'dom_interaction', + SCROLL_PERCENTAGE = 'scroll_percentage', + CODE_TRIGGER = 'code_trigger', + REVENUE = 'revenue' +} /** * Defines how and when an experience associated with this location should be activated for a visitor who matches the location's rules. @@ -2299,23 +2103,12 @@ export type LocationTrigger = LocationTriggerDomElement | LocationTriggerCallbac * Note: For Full Stack projects, `upon_run` is effectively the only mode, as activation is handled by the SDK. * */ -export type LocationTriggerTypes = 'upon_run' | 'manual' | 'dom_element' | 'callback'; - -/** - * Specifies the mechanism that activates an experience when its location rules are met: - * - `upon_run`: (Default) The experience activates as soon as the Convert tracking script loads and evaluates that the visitor matches the location's rules (e.g., URL match). This is the standard behavior for most A/B tests. - * - `manual`: The experience only activates when explicitly triggered by a JavaScript call (`window._conv_q.push({ what: 'triggerLocation', params: { locationId: '...' } })`). Gives precise programmatic control over activation. - * - `dom_element`: The experience activates upon a specific user interaction (e.g., 'click', 'hover', 'in_view', 'change') with a defined DOM element (identified by a CSS `selector`). Useful for testing changes related to interactive elements. - * - `callback`: The experience activates when a custom JavaScript `callback` function (provided in `js`) calls the `activate()` function passed to it. Allows for complex asynchronous activation logic, e.g., after an API response or a specific SPA state change. - * Note: For Full Stack projects, `upon_run` is effectively the only mode, as activation is handled by the SDK. - * - */ -export const LocationTriggerTypes = { - UPON_RUN: 'upon_run', - MANUAL: 'manual', - DOM_ELEMENT: 'dom_element', - CALLBACK: 'callback' -} as const; +export enum LocationTriggerTypes { + UPON_RUN = 'upon_run', + MANUAL = 'manual', + DOM_ELEMENT = 'dom_element', + CALLBACK = 'callback' +} export type LocationTriggerBase = { type: LocationTriggerTypes; @@ -2325,31 +2118,17 @@ export type LocationTriggerUponRun = LocationTriggerBase & { type?: 'upon_run'; }; -export type type19 = 'upon_run'; - -export const type19 = { - UPON_RUN: 'upon_run' -} as const; +export enum type19 { + UPON_RUN = 'upon_run' +} export type LocationTriggerManual = LocationTriggerBase & { type?: 'manual'; }; -export type type20 = 'manual'; - -export const type20 = { - MANUAL: 'manual' -} as const; - -/** - * The type of user interaction with a DOM element that will trigger the experience: - * - `click`: Activates when the element is clicked. - * - `hover`: Activates when the mouse pointer hovers over the element (mouseenter). - * - `in_view`: Activates when the element becomes visible in the browser's viewport (e.g., user scrolls to it). KB: "Launch Experiments Using Custom JavaScript When Elements Appear in DOM". - * - `change`: Activates when the value of a form element (like input, select, textarea) changes. - * - */ -export type LocationDomTriggerEvents = 'click' | 'hover' | 'in_view' | 'change'; +export enum type20 { + MANUAL = 'manual' +} /** * The type of user interaction with a DOM element that will trigger the experience: @@ -2359,12 +2138,12 @@ export type LocationDomTriggerEvents = 'click' | 'hover' | 'in_view' | 'change'; * - `change`: Activates when the value of a form element (like input, select, textarea) changes. * */ -export const LocationDomTriggerEvents = { - CLICK: 'click', - HOVER: 'hover', - IN_VIEW: 'in_view', - CHANGE: 'change' -} as const; +export enum LocationDomTriggerEvents { + CLICK = 'click', + HOVER = 'hover', + IN_VIEW = 'in_view', + CHANGE = 'change' +} export type LocationTriggerDomElement = LocationTriggerBase & { type?: 'dom_element'; @@ -2378,11 +2157,9 @@ export type LocationTriggerDomElement = LocationTriggerBase & { events: Array; }; -export type type21 = 'dom_element'; - -export const type21 = { - DOM_ELEMENT: 'dom_element' -} as const; +export enum type21 { + DOM_ELEMENT = 'dom_element' +} export type LocationTriggerCallback = LocationTriggerBase & { type?: 'callback'; @@ -2411,11 +2188,9 @@ export type LocationTriggerCallback = LocationTriggerBase & { js: string; }; -export type type22 = 'callback'; - -export const type22 = { - CALLBACK: 'callback' -} as const; +export enum type22 { + CALLBACK = 'callback' +} /** * Base Location object @@ -2592,30 +2367,20 @@ export type ConfigProject = { /** * Value which describes project product type */ -export type type23 = 'fullstack' | 'web'; - -/** - * Value which describes project product type - */ -export const type23 = { - FULLSTACK: 'fullstack', - WEB: 'web' -} as const; +export enum type23 { + FULLSTACK = 'fullstack', + WEB = 'web' +} /** * Follow the 'Do not track' browser settings for users in the mentioned area of the world. */ -export type do_not_track = 'OFF' | 'EU ONLY' | 'EEA ONLY' | 'Worldwide'; - -/** - * Follow the 'Do not track' browser settings for users in the mentioned area of the world. - */ -export const do_not_track = { - OFF: 'OFF', - EU_ONLY: 'EU ONLY', - EEA_ONLY: 'EEA ONLY', - WORLDWIDE: 'Worldwide' -} as const; +export enum do_not_track { + OFF = 'OFF', + EU_ONLY = 'EU ONLY', + EEA_ONLY = 'EEA ONLY', + WORLDWIDE = 'Worldwide' +} /** * Follow Global Privacy Control (GPC) signals for users in the mentioned area of the world. @@ -2625,22 +2390,12 @@ export const do_not_track = { * - Worldwide: Follow GPC signals for users worldwide. * */ -export type global_privacy_control = 'OFF' | 'EU ONLY' | 'EEA ONLY' | 'Worldwide'; - -/** - * Follow Global Privacy Control (GPC) signals for users in the mentioned area of the world. - * - OFF: Do not follow GPC signals. - * - EU ONLY: Follow GPC signals for users in the European Union only. - * - EEA ONLY: Follow GPC signals for users in the European Economic Area only. - * - Worldwide: Follow GPC signals for users worldwide. - * - */ -export const global_privacy_control = { - OFF: 'OFF', - EU_ONLY: 'EU ONLY', - EEA_ONLY: 'EEA ONLY', - WORLDWIDE: 'Worldwide' -} as const; +export enum global_privacy_control { + OFF = 'OFF', + EU_ONLY = 'EU ONLY', + EEA_ONLY = 'EEA ONLY', + WORLDWIDE = 'Worldwide' +} /** * Settings to identify which tracking script version will be applied to the project. @@ -2758,15 +2513,10 @@ export type VisitorTrackingEvents = { /** * Type of the event. It can be a bucketing or a conversion event */ -export type eventType = 'bucketing' | 'conversion'; - -/** - * Type of the event. It can be a bucketing or a conversion event - */ -export const eventType = { - BUCKETING: 'bucketing', - CONVERSION: 'conversion' -} as const; +export enum eventType { + BUCKETING = 'bucketing', + CONVERSION = 'conversion' +} /** * Bucketing event data @@ -2870,55 +2620,33 @@ export type VisitorSegments = { * OTH - Other * */ -export type browser = 'IE' | 'CH' | 'FF' | 'OP' | 'SF' | 'OTH'; - -/** - * Browser used: - * IE - Internet Explorer - * CH - Chrome - * FF - Firefox - * OP - Opera - * SF - Safari - * OTH - Other - * - */ -export const browser = { - IE: 'IE', - CH: 'CH', - FF: 'FF', - OP: 'OP', - SF: 'SF', - OTH: 'OTH' -} as const; +export enum browser { + IE = 'IE', + CH = 'CH', + FF = 'FF', + OP = 'OP', + SF = 'SF', + OTH = 'OTH' +} /** * Traffic source */ -export type source = 'campaign' | 'search' | 'referral' | 'direct' | 'ai_tool'; - -/** - * Traffic source - */ -export const source = { - CAMPAIGN: 'campaign', - SEARCH: 'search', - REFERRAL: 'referral', - DIRECT: 'direct', - AI_TOOL: 'ai_tool' -} as const; - -/** - * Type of the visitor - */ -export type visitorType = 'new' | 'returning'; +export enum source { + CAMPAIGN = 'campaign', + SEARCH = 'search', + REFERRAL = 'referral', + DIRECT = 'direct', + AI_TOOL = 'ai_tool' +} /** * Type of the visitor */ -export const visitorType = { - NEW: 'new', - RETURNING: 'returning' -} as const; +export enum visitorType { + NEW = 'new', + RETURNING = 'returning' +} /** * Response containing project's visitor data From 38cc9a916077733310d6f1c4e0b0779e2610651a Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Wed, 20 May 2026 22:41:19 +0300 Subject: [PATCH 10/11] fix(ci): pin yarn to 4.10.3 and regenerate lockfile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The yarn.lock on main-convert was bumped to lockfile metadata `version: 9` by a local install with yarn >=4.11. The backend's V1 tracking build runs `yarn install` in immutable mode under yarn 4.10.3 (per `public/js/tracking/package.json` packageManager field), which writes `version: 8` lockfiles — triggering YN0028 and failing staging deploys. Pinning `packageManager: yarn@4.10.3` here makes the toolchain explicit and prevents future drift when contributors run install with a newer yarn. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.json | 1 + yarn.lock | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index bbc1a68e..ba7c5431 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "demo:cloudflare:start": "cd demo/cloudflare-workers && yarn dev" }, "private": true, + "packageManager": "yarn@4.10.3+sha512.c38cafb5c7bb273f3926d04e55e1d8c9dfa7d9c3ea1f36a4868fa028b9e5f72298f0b7f401ad5eb921749eb012eb1c3bb74bf7503df3ee43fd600d14a018266f", "workspaces": [ "packages/*", "demo/*" diff --git a/yarn.lock b/yarn.lock index 809a61b6..bb421d8d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 9 + version: 8 cacheKey: 10c0 "@alloc/quick-lru@npm:^5.2.0": From 90e4730386a4cceb9ce35e484654f84f3c33709c Mon Sep 17 00:00:00 2001 From: Ahmed Abbas Date: Thu, 21 May 2026 03:47:08 +0300 Subject: [PATCH 11/11] fix(context): forward all BucketingAttributes to ExperienceManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context.runExperience and Context.runExperiences rebuilt a fresh attributes object with only four hardcoded keys (visitorProperties, locationProperties, updateVisitorProperties, environment) before forwarding to ExperienceManager.selectVariation/selectVariations. This silently dropped every other BucketingAttributes field — enableTracking, forceVariationId, ignoreLocationProperties, typeCasting, experienceKeys — so callers opting out of tracking, forcing a variation, or ignoring location targeting were silently ignored. DataManager._getBucketingByField destructures these by name with enableTracking defaulting to `true`, which is how the opt-out was being lost. Switch to spread-then-override so all caller-supplied attributes pass through while still applying the two transforms Context must do: merging visitorProperties via getVisitorProperties() and defaulting environment to the Context's own environment. Add tests covering forwarding of enableTracking, forceVariationId, ignoreLocationProperties, and updateVisitorProperties through both runExperience and runExperiences. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/js-sdk/src/context.ts | 6 +-- packages/js-sdk/tests/context.tests.ts | 72 ++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/packages/js-sdk/src/context.ts b/packages/js-sdk/src/context.ts index f83180f6..4afb57de 100644 --- a/packages/js-sdk/src/context.ts +++ b/packages/js-sdk/src/context.ts @@ -136,9 +136,8 @@ export class Context implements ContextInterface { this._visitorId, experienceKey, { + ...attributes, visitorProperties, // represents audiences - locationProperties: attributes?.locationProperties, // represents site_area/locations - updateVisitorProperties: attributes?.updateVisitorProperties, environment: attributes?.environment || this._environment } ); @@ -190,9 +189,8 @@ export class Context implements ContextInterface { const bucketedVariations = this._experienceManager.selectVariations( this._visitorId, { + ...attributes, visitorProperties, // represents audiences - locationProperties: attributes?.locationProperties, // represents site_area/locations - updateVisitorProperties: attributes?.updateVisitorProperties, environment: attributes?.environment || this._environment } ); diff --git a/packages/js-sdk/tests/context.tests.ts b/packages/js-sdk/tests/context.tests.ts index 44742f09..1230bf4e 100644 --- a/packages/js-sdk/tests/context.tests.ts +++ b/packages/js-sdk/tests/context.tests.ts @@ -179,6 +179,78 @@ describe('Context tests', function () { done ); }); + it('Should forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperience', function () { + const experienceKey = 'test-experience-ab-fullstack-2'; + const originalSelectVariation = + experienceManager.selectVariation.bind(experienceManager); + let capturedAttributes; + experienceManager.selectVariation = function ( + capturedVisitorId, + capturedExperienceKey, + attributes + ) { + capturedAttributes = attributes; + return originalSelectVariation( + capturedVisitorId, + capturedExperienceKey, + attributes + ); + }; + try { + context.runExperience(experienceKey, { + locationProperties: {url: 'https://convert.com/'}, + visitorProperties: {varName3: 'something'}, + enableTracking: false, + forceVariationId: '100299461', + ignoreLocationProperties: true, + updateVisitorProperties: true + }); + expect(capturedAttributes).to.include({ + enableTracking: false, + forceVariationId: '100299461', + ignoreLocationProperties: true, + updateVisitorProperties: true + }); + expect(capturedAttributes.locationProperties).to.deep.equal({ + url: 'https://convert.com/' + }); + } finally { + experienceManager.selectVariation = originalSelectVariation; + } + }); + it('Should forward BucketingAttributes (enableTracking, forceVariationId, ignoreLocationProperties) through runExperiences', function () { + const originalSelectVariations = + experienceManager.selectVariations.bind(experienceManager); + let capturedAttributes; + experienceManager.selectVariations = function ( + capturedVisitorId, + attributes + ) { + capturedAttributes = attributes; + return originalSelectVariations(capturedVisitorId, attributes); + }; + try { + context.runExperiences({ + locationProperties: {url: 'https://convert.com/'}, + visitorProperties: {varName3: 'something'}, + enableTracking: false, + forceVariationId: '100299461', + ignoreLocationProperties: true, + updateVisitorProperties: true + }); + expect(capturedAttributes).to.include({ + enableTracking: false, + forceVariationId: '100299461', + ignoreLocationProperties: true, + updateVisitorProperties: true + }); + expect(capturedAttributes.locationProperties).to.deep.equal({ + url: 'https://convert.com/' + }); + } finally { + experienceManager.selectVariations = originalSelectVariations; + } + }); it('Shoud successfully get a single feature and its status', function (done) { this.timeout(test_timeout); getSingleFeatureWithStatus(