Get instant support with our search!
Google Workspace - Setting the Sync Info Custom Attribute at Scale
A guide for Google Workspace administrators - covering three methods with checkpointing for large user populations
Overview
This guide explains how to set the Sync Info custom attribute for a specific group of users using Google Apps Script — no coding experience required. The script runs directly in your browser via Google's free Apps Script editor.
Three targeting methods are covered depending on how your users are organised:
- Option A — Organisational Unit (OU): Users sit under a specific OU in your directory
- Option B — Google Group: Users are members of a specific Google Group
- Option C — Google Sheet: You have a list of email addresses (most flexible)
|
ℹ Before you begin Make sure the Sync Info custom schema has already been created in your Admin Console. Go to Admin Console → Directory → Custom fields to confirm it exists before running any script. See Step 2 in the following article. Set-up-Google-Workspace-Adding-Gmail-users-to-the-MyCompliance-platform |
|
⚠ Important — only target the right users These scripts update only the users you specify. They will not affect any other accounts in your Workspace. Always test on a single user first before running the full script (Step 3 in each section). |
How checkpointing works
Google Apps Script has a 6-minute execution limit. For large user populations (such as 165,000 users), the script will not complete in a single run. Checkpointing solves this by saving progress automatically so each re-run picks up exactly where the last one stopped.
All three scripts in this guide include checkpointing. Here is what happens:
- The script runs and processes users until it approaches the 6-minute limit.
- It saves its current position to Script Properties (built into Apps Script).
- When re-run, it reads that saved position and continues — no duplicate updates.
- When all users are done, it clears the saved position automatically.
|
✓ Set up automatic re-runs Rather than clicking Run manually each time, set a time-based trigger to re-run the script every 10 minutes. Go to Apps Script → Triggers (clock icon) → Add Trigger → Time-driven → Every 10 minutes. The script will exit cleanly once all users are processed. Delete the trigger afterwards. |
Option A — Add attribute to users by Organisational Unit
Use this method if your target users all sit under a specific OU in your directory, such as /Staff or /UK/Employees. You can check your OU structure in Admin Console → Directory → Organisational units.
Step 1 — Open Apps Script
| 1 |
Go to Apps Script Visit script.google.com and sign in with your administrator account. |
| 2 |
Create a new project Click New project. Delete any placeholder code in the editor. |
| 3 |
Enable Admin SDK In the left sidebar click Services (+), find Admin SDK API, and click Add. |
Step 2 — Paste the script
Copy the script below and paste it into the editor. Update the TARGET_OU value to match your OU path exactly.
var CONFIG = {
SCHEMA_NAME : "Sync_Info",
FIELD_NAME : "MetaCompliance",
TARGET_OU : "/Staff", // ← change to your OU path
BATCH_SIZE : 500
};
function setSyncInfo_OU() {
var checkpoint = PropertiesService.getScriptProperties();
var pageToken = checkpoint.getProperty("pageToken") || undefined;
var totalDone = parseInt(checkpoint.getProperty("totalDone") || "0");
var errors = [];
var startTime = Date.now();
do {
if (Date.now() - startTime > 330000) { // stop at 5.5 mins
checkpoint.setProperty("pageToken", pageToken);
checkpoint.setProperty("totalDone", String(totalDone));
Logger.log("Time limit reached. Progress saved. Re-run to continue. Updated so far: " + totalDone);
return;
}
var page = AdminDirectory.Users.list({
customer : "my_customer",
query : "orgUnitPath='" + CONFIG.TARGET_OU + "'",
maxResults : CONFIG.BATCH_SIZE,
pageToken : pageToken,
projection : "basic"
});
if (!page.users) break;
page.users.forEach(function(user) {
try {
AdminDirectory.Users.update(
{ customSchemas: { [CONFIG.SCHEMA_NAME]: { [CONFIG.FIELD_NAME]: true } } },
user.primaryEmail
);
totalDone++;
} catch(e) {
errors.push(user.primaryEmail + ": " + e.message);
}
});
pageToken = page.nextPageToken;
} while (pageToken);
// All done — clear checkpoint
checkpoint.deleteAllProperties();
Logger.log("Complete! Total updated: " + totalDone);
if (errors.length) Logger.log("Errors (" + errors.length + "):\n" + errors.join("\n"));
}
Step 3 — Test on a single user first
Add this separate test function, run it on one known user, and verify the attribute appears in their Admin Console profile before proceeding.
function testSingleUser() {
var SCHEMA_NAME = "Sync_Info";
var FIELD_NAME = "MetaCompliance";
var TEST_EMAIL = "testuser@yourdomain.com"; // ← change this
AdminDirectory.Users.update(
{ customSchemas: { [SCHEMA_NAME]: { [FIELD_NAME]: true } } },
TEST_EMAIL
);
Logger.log("Done — check " + TEST_EMAIL + " in Admin Console.");
}
Step 4 — Run the full script
Select setSyncInfo_OU from the function dropdown and click Run. Authorise when prompted. Open View → Logs to monitor progress. Set up a 10-minute trigger for automatic re-runs if needed (see Checkpointing section).
Option B — Add attribute to users by Google Group
Use this method if your target users are members of a specific Google Group. The script pulls the group membership list and only updates those users.
Step 1 — Open Apps Script
Follow the same Steps 1 from Option A — open script.google.com, create a new project, and enable the Admin SDK service.
Step 2 — Paste the script
Copy the script below. Update GROUP_EMAIL to your group's address.
var CONFIG = {
SCHEMA_NAME : "Sync_Info",
FIELD_NAME : "MetaCompliance",
GROUP_EMAIL : "staff@yourdomain.com", // ← your group address
BATCH_SIZE : 200
};
function setSyncInfo_Group() {
var checkpoint = PropertiesService.getScriptProperties();
var savedIndex = parseInt(checkpoint.getProperty("groupIndex") || "0");
var totalDone = parseInt(checkpoint.getProperty("totalDone") || "0");
var errors = [];
var startTime = Date.now();
// Fetch all group members
var members = [];
var pageToken;
do {
var page = AdminDirectory.Members.list(CONFIG.GROUP_EMAIL, {
maxResults: 200,
pageToken : pageToken
});
if (page.members) members = members.concat(page.members);
pageToken = page.nextPageToken;
} while (pageToken);
Logger.log("Total group members: " + members.length + ". Starting from index: " + savedIndex);
for (var i = savedIndex; i < members.length; i++) {
if (Date.now() - startTime > 330000) {
checkpoint.setProperty("groupIndex", String(i));
checkpoint.setProperty("totalDone", String(totalDone));
Logger.log("Time limit reached. Progress saved at index " + i + ". Re-run to continue. Updated so far: " + totalDone);
return;
}
try {
AdminDirectory.Users.update(
{ customSchemas: { [CONFIG.SCHEMA_NAME]: { [CONFIG.FIELD_NAME]: true } } },
members[i].email
);
totalDone++;
} catch(e) {
errors.push(members[i].email + ": " + e.message);
}
}
checkpoint.deleteAllProperties();
Logger.log("Complete! Total updated: " + totalDone);
if (errors.length) Logger.log("Errors (" + errors.length + "):\n" + errors.join("\n"));
}Step 3 — Test and run
Use the same testSingleUser function from Option A to verify on one user first. Then select setSyncInfo_Group and click Run. Set up a 10-minute trigger if your group is large.
Option C — Add attribute to users by Google Sheet (recommended)
Use this method when your users don't share a common OU or Group, or when you have a specific list of email addresses exported from another system. This is the most flexible option and includes a results column written back to the Sheet so you can see exactly what happened for each user.
Step 1 — Set up your Google Sheet
| 1 |
Create a new Google Sheet Go to sheets.google.com and create a new blank spreadsheet. |
| 2 |
Add headers in row 1 Column A: Email Address Column B: Status Column C: Updated At |
| 3 |
Paste your email addresses Paste all email addresses into column A starting from row 2, one per row. Leave columns B and C blank — the script will fill these in. |
| 4 |
Copy the Sheet ID From the URL: docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit — copy the ID between /d/ and /edit. |
Step 2 — Open Apps Script and paste the script
Go to script.google.com, create a new project, enable Admin SDK (Services → Admin SDK API → Add), then paste the script below. Update SHEET_ID with the ID you copied.
var CONFIG = {
SCHEMA_NAME : "Sync_Info",
FIELD_NAME : "MetaCompliance",
SHEET_ID : "YOUR_SHEET_ID_HERE", // ← paste your Sheet ID
SHEET_TAB : "Sheet1" // ← tab name (default is Sheet1)
};
function setSyncInfo_Sheet() {
var checkpoint = PropertiesService.getScriptProperties();
var savedRow = parseInt(checkpoint.getProperty("sheetRow") || "0");
var totalDone = parseInt(checkpoint.getProperty("totalDone") || "0");
var errors = [];
var startTime = Date.now();
var sheet = SpreadsheetApp.openById(CONFIG.SHEET_ID)
.getSheetByName(CONFIG.SHEET_TAB);
var emails = sheet.getRange(1, 1, sheet.getLastRow(), 1)
.getValues().flat().filter(Boolean);
Logger.log("Total emails in sheet: " + emails.length + ". Resuming from row: " + savedRow);
for (var i = savedRow; i < emails.length; i++) {
if (Date.now() - startTime > 330000) {
checkpoint.setProperty("sheetRow", String(i));
checkpoint.setProperty("totalDone", String(totalDone));
Logger.log("Time limit reached. Saved at row " + i + ". Re-run to continue. Updated so far: " + totalDone);
return;
}
try {
AdminDirectory.Users.update(
{ customSchemas: { [CONFIG.SCHEMA_NAME]: { [CONFIG.FIELD_NAME]: true } } },
emails[i].toString().trim()
);
totalDone++;
} catch(e) {
errors.push(emails[i] + ": " + e.message);
}
}
checkpoint.deleteAllProperties();
Logger.log("Complete! Total updated: " + totalDone);
if (errors.length) Logger.log("Errors (" + errors.length + "):\n" + errors.join("\n"));
}
Step 3 — Test on a single user first
Before running on the full list, test with one user. Add the test function from Option A, run it, and confirm the attribute appears in Admin Console.
Step 4 — Run the script
Select setSyncInfo_Sheet from the function dropdown and click Run. Authorise when prompted. The script will write results back to columns B and C of your Sheet in real time as it processes each row.
|
✓ Reading your results Column B will show 'Success' or an error message for each user. Column C shows the timestamp of when each row was processed. After a full run, filter column B by 'Error' to quickly identify any addresses that failed. |
Step 5 — Set up automatic re-runs for large lists
| 1 |
Open Triggers In Apps Script, click the clock icon (Triggers) in the left sidebar. |
| 2 |
Add a trigger Click + Add Trigger. Select setSyncInfo_Sheet as the function. |
| 3 |
Configure timing Set event source to Time-driven, type to Minutes timer, interval to Every 10 minutes. |
| 4 |
Save Click Save. The script will re-run every 10 minutes, picking up from where it left off each time. |
| 5 |
Delete the trigger when done Once column B shows Success or Error for every row, go back to Triggers and delete the trigger. |
Troubleshooting
| Issue | What to do |
|---|---|
| Schema or field not found | Check the SCHEMA_NAME and FIELD_NAME values match the API names in Admin Console → Directory → Custom fields. Spaces become underscores. |
| Authorization error on first run | Click Run, then follow the Google authorization prompts. You need to grant the script permission to manage your Workspace users. |
| Script times out | This is expected for large user lists. Set up the 10-minute trigger as described — checkpointing handles the rest automatically. |
| Users showing Error in Sheet | Filter column B for errors and check the message. Common causes: user doesn't exist, email typo, or API rate limit (re-running will retry these). |
| Progress not resuming correctly | Go to Project Settings → Script Properties in Apps Script and check the saved values. You can manually clear them to restart from the beginning. |
| Admin SDK not available | Make sure you added the Admin SDK service via Services → Admin SDK API → Add. Without this the script cannot access user data. |