The Change Sync feature keeps non-production environments in line with production changes by syncing selected objects automatically. When a change is detected in the listening environment, InProd executes an associated Changeset against the target environment.
The Changeset runs in Enforcing mode: if the object already exists in the target environment it is updated; if it does not exist it is created.
The Change Sync list shows all rules configured for the current tenant. Rules are grouped by object type in the folder tree on the left panel — clicking a folder filters the list to that object type.
List columns:
The Run History button opens the operation log for all Change Sync runs.
Each row has a Clone action (duplicates the rule and its Changeset) and a Delete action. The Delete button is disabled while the rule is Active — deactivate the rule first before deleting.
Click New to open the create dialog. All fields are required:
After creation, InProd automatically generates a Changeset in Enforcing mode targeting the receiving environment, with a single Create action pre-populated with [?? sync_object.fieldName ??] template variables for every field on the selected object type. This provides a starting point — review and edit the Changeset actions before activating the rule.
Note: On the first Celery task run after a rule is created, InProd records the current position in the audit history but does not process any existing changes. Only changes that occur after that first run will be synced.
The detail page is divided into three columns.
Free-text description of the rule. Click to edit inline.
When both Create and Update are enabled and the same object changes multiple times within one sync cycle, InProd collapses those events and executes the Changeset once using the object's final state.
Changes caused by a Changeset run are excluded from Change Sync processing to prevent feedback loops.
The Matching Type controls which detected objects trigger the Changeset.
Every detected change for the selected object type triggers the Changeset. No additional configuration is required. This is the default.
Shows a Matching Query text field. This matching type is a placeholder in the current release — the query field is stored but not evaluated at runtime. Changes are processed the same as the All type. Use the JS type for custom filtering logic.
A JavaScript expression evaluated against each changed object. Only objects where the expression returns true trigger the Changeset. Click Edit JS Script to open the code editor.
The variable sync_object is available in the script and contains the full final state of the changed object as a flat JavaScript object. See JavaScript Matching Expression below for full syntax, examples, and best practices.
When a Change Sync rule is created, InProd automatically builds a Changeset with a default Create action. Every field on the selected object type is pre-populated using Changeset template variables of the form [?? sync_object.fieldName ??], which are resolved at execution time using the changed object's data. For example, to replicate the name exactly:
[?? sync_object.name ??]
Note that [?? sync_object.name ??] is Changeset template syntax, not JavaScript. It is distinct from the sync_object JavaScript variable used in the JS matching script — both use the same underlying data but in different contexts.
Fields that reference other objects (such as divisions or queues) typically need manual adjustment to map correctly between environments. Review all action parameters before activating the rule.
The Run History page shows the operation log for all Change Sync executions. Each entry records when the sync ran, which rule triggered it, and whether the Changeset succeeded or failed. Use this page to verify rules are firing as expected and to investigate errors.
The JavaScript matching expression filters which detected changes should trigger the Changeset. When an object is created or updated in Genesys Cloud, the Change Sync engine evaluates your JavaScript code against each changed object. Only objects where the script returns true proceed to execute the Changeset.
The JavaScript engine is QuickJS, which supports ES2020 syntax. Modern JavaScript features including const, let, arrow functions, template literals, and includes() are fully supported.
sync_object.true, the change is processed by the Changeset. Any other return value (including false, undefined, null, numbers, strings, etc.) causes the change to be skipped.| Variable | Type | Description |
|---|---|---|
sync_object |
Object | The Genesys Cloud object that was changed, containing all of its properties as key-value pairs |
sync_object?The properties available depend on the object type configured on the Change Sync rule. The sync_object is a flat JavaScript object (dictionary) where each key is a field name and each value is the field's current value.
Common properties shared by most object types:
| Property | Type | Description |
|---|---|---|
name |
String | The name of the object |
description |
String | The description of the object (if applicable) |
state |
String | The current state (e.g., "active", "inactive", "deleted") |
division |
String | The ID of the division the object belongs to |
GenCloudRoutingQueues)This is an example of the properties available on the Genesys Cloud Queues object.
| Property | Type | Example |
|---|---|---|
name |
String | "Sales_Queue" |
description |
String | "Main sales queue" |
division |
String | Division ID |
scoringMethod |
String | "TimestampAndPriority" |
skillEvaluationMethod |
String | "ALL", "BEST", "DISREGARD" |
autoAnswerOnly |
Boolean | true / false |
enableTranscription |
Boolean | true / false |
enableManualAssignment |
Boolean | true / false |
memberCount |
Integer | 25 |
Tip: The properties on
sync_objectmatch the field names shown in the InProd object configuration view for the selected object type.
| Function | Description |
|---|---|
logMsg(message) |
Writes a log message for debugging purposes. The message will appear in the application logs. |
The following features are available (ES2020):
var, let, const declarations=>)function declarations and expressionsif / else / else iffor, while, do...while loopsswitch / casetry / catch / finallyindexOf(), includes(), forEach(), map(), filter(), some(), every(), find(), findIndex()indexOf(), includes(), substring(), startsWith(), endsWith(), toLowerCase(), toUpperCase(), split(), trim(), replace(), match(), search()JSON.parse(), JSON.stringify()/pattern/flags)typeof, instanceofcondition ? a : b)The following are not available (sandbox — no DOM, browser, or network APIs):
Promise, async/awaitfetch(), XMLHttpRequest, setTimeout, setIntervaldocument, window, console — use logMsg() insteadYour script must return a boolean true for the change to be processed. All other return values are treated as "do not process":
| Return Value | Result |
|---|---|
true |
Change is processed |
false |
Change is skipped |
undefined |
Change is skipped |
null |
Change is skipped |
1 (or any number) |
Change is skipped |
"true" (string) |
Change is skipped |
These are single-line expressions that return a boolean directly. No function wrapper is needed.
Match queues whose name starts with a prefix:
sync_object['name'].indexOf('PROD_') == 0
Match objects where the name contains a keyword:
sync_object['name'].indexOf('Sales') !== -1
Match users with a specific email domain:
sync_object['email'].indexOf('@company.com') !== -1
Match queues that have transcription enabled:
sync_object['enableTranscription'] == true
Match active objects only:
sync_object['state'] == 'active'
For more complex logic, wrap your code in a function and call it. This allows you to use multiple statements, variables, and conditional logic.
Match queues in a specific division with a name pattern:
function match() {
var name = sync_object['name'];
var divisionId = sync_object['division'];
if (name.indexOf('PROD_') == 0 && divisionId == 'your-division-id-here') {
return true;
}
return false;
}
match()
Match objects based on multiple name prefixes:
function match() {
var name = sync_object['name'];
var prefixes = ['PROD_', 'LIVE_', 'MAIN_'];
for (var i = 0; i < prefixes.length; i++) {
if (name.indexOf(prefixes[i]) == 0) {
return true;
}
}
return false;
}
match()
Exclude specific objects by name:
function match() {
var name = sync_object['name'];
var excluded = ['Test_Queue', 'Dev_Queue', 'Sandbox_Queue'];
for (var i = 0; i < excluded.length; i++) {
if (name == excluded[i]) {
return false;
}
}
return true;
}
match()
Match queues using a regular expression:
function match() {
var name = sync_object['name'];
var pattern = /^(PROD|LIVE)_.*_Queue$/;
return pattern.test(name);
}
match()
Case-insensitive name matching:
function match() {
var name = sync_object['name'].toLowerCase();
return name.indexOf('sales') !== -1;
}
match()
logMsg for DebuggingThe logMsg() function writes messages to the application logs, which is useful for understanding what data is available on sync_object and troubleshooting matching logic.
Log the object name and then match:
function match() {
logMsg('Processing object: ' + sync_object['name']);
logMsg('Object state: ' + sync_object['state']);
if (sync_object['name'].indexOf('PROD_') == 0) {
logMsg('Matched: ' + sync_object['name']);
return true;
}
logMsg('Skipped: ' + sync_object['name']);
return false;
}
match()
Log all available properties on the object (useful for discovery):
function match() {
for (var key in sync_object) {
logMsg('Property: ' + key + ' = ' + sync_object[key]);
}
return false;
}
match()
Tip: Set the script to return
falsewhile debugging so no changes are actually processed. Once you understand the data, update the logic and change the return value.
Match queues whose name ends with a specific suffix:
function match() {
var name = sync_object['name'];
var suffix = '_Callback';
return name.indexOf(suffix, name.length - suffix.length) !== -1;
}
match()
Match objects using a naming convention with exclusions:
function match() {
var name = sync_object['name'];
// Only sync queues in the production naming convention: CC_[Region]_[Function]
var pattern = /^CC_[A-Z]{2,4}_/;
if (!pattern.test(name)) {
return false;
}
// Exclude any temporary queues
if (name.indexOf('_TEMP') !== -1 || name.indexOf('_TEST') !== -1) {
return false;
}
return true;
}
match()
Match based on description content:
function match() {
var desc = sync_object['description'];
if (typeof desc === 'string' && desc.indexOf('[managed]') !== -1) {
return true;
}
return false;
}
match()
Always check for undefined values before accessing string methods. If a property might not exist on the object, use a typeof check first:
typeof sync_object['description'] === 'string' && sync_object['description'].indexOf('keyword') !== -1
Use logMsg() during development to inspect the sync_object contents, then remove or reduce logging for production rules.
Keep expressions simple when possible — a single-line expression is easier to maintain than a complex function.
Use === for strict comparison — prefer === over == to avoid unexpected type coercion. Use == only when loose equality is intentional.
Test with return false first — when writing a new matching expression, start by logging and returning false to verify your script runs without errors before enabling actual processing.