Google Drive’s Shared Drives are designed a little differently than regular Google Drive folders. Each Shared Drive file is collectively owned by the group working on the file or, more directly, the Google Workspace Domain account that manages the file.
While you can search for shared drives and get some level of metadata (e.g. who has what permissions) from them as you can see in this tutorial:
Get a list of Google Shared Drives by ID and Name in Google Apps Script [updated 10 Feb 2022]
… you won’t see details of who created the shared drive with DriveApp or the Drive API advanced service in Google Apps Script.
After a bit of experimentation, I built a solution that uses:
- The Drive Activity API to extract the creator’s numerical ID.
- The Admin SDK to search for the user by ID and retrieve their email.
Check out the video tutorial below, then grab a copy of the script along with links and a brief discussion of some of the more interesting and technical bits of the code.
The Video
The Code
The main function here is the getSharedDriveCreator()
function. If you are just copying and pasting then this will be all you need to add to your project.
All you need to do is add the ID of your shared drive as the first parameter of the function:
getSharedDriveCreator("0APU21xY4hn2STek9PVA")
The runsies()
function is just an example function showing how everything works and is not needed in your own project, but may be useful for testing.
You will need to add two Google Apps Script advanced services to your script:
I haven’t changed the reference in either of these services here, but if you do, you will need to update the script.
If you have found the tutorial helpful, why not shout me a coffee ☕? I'd really appreciate it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
/** * #### Get The Creator's Email of a Shared Drive #### * @author Scott Donald <scott@yagisanatode.com> * @see {@link https://yagisanatode.com/get-the-creators-email-of-a-shared-drive-with-google-apps-script/} for the tutorial. */ /** * Collects the email of the creator of the shared drive. * @param {String} id - The selected Shared Drive ID. * @returns {String} The email of the creator of the Shared Drive. */ function getSharedDriveCreator(id) { // Check the activity log for the selected folder id. const activity = DriveActivity.Activity.query( { "itemName": "items/" + id, "filter": "detail.action_detail_case:CREATE" } ) // Extract the person's name (aka their unique id.) const personName = activity.activities[0].actors[0].user.knownUser.personName const accountId = personName.substring(7) // Removes ("person/") // Get's the selected user's details from the Admin Directory SDK. let user; try { // If non-admin user. user = AdminDirectory.Users.get(accountId, { "projection": "basic", "viewType": "domain_public" }) }catch(e){ // If active user has admin control. user = AdminDirectory.Users.get(accountId) } const email = user.primaryEmail return email; } /** * An example function used to show how to implement it in your own project. */ function runsies() { const creatorEmail = getSharedDriveCreator("0APU21xY4hn2STek9PVA") console.log(creatorEmail) } |
Code Walkthrough of the Shared Drive Creator function
Get the activity records of the shared drive
The first task in this script is to invoke the Google Drive Activity API DriveActivity class. You can use this API to:
- See what has changed on a file or folder.
- See who made those changes.
- Provide alerts when changes or comments have been made.
We can create an activity query with the API using DriveActivity.Activity.query()
. The query will return an object containing a historical log of all the interactions on the selected file or folder.
The query takes a single object as a parameter. We are specifying a particular location to run our query so we need to add the “itemName” property.
Strangely the value of the “itemName” needs to contain “items/” and then the file or folder id.
Next, we can filter the returned object down to contain information about the creation of the file or folder. This is achieved with the detail.action_detail_case:
field. In these filter fields, the colon (:) is an operator representing “has”. Here we can add “CREATE” to reduce our search to only show information about the creation of the file or folder. Basically, this says:
“In the folder, show me the details related to the creation action.”
This will return an object that looks a little like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
|
{ "activities": [ { "actions": [ { "detail": { "create": { "new": {} } } } ], "primaryActionDetail": { "create": { "new": {} } }, "timestamp": "2022-12-14T08:54:03.517Z", "targets": [ { "teamDrive": { "title": "test drive", "root": { "driveFolder": { "type": "SHARED_DRIVE_ROOT" }, "name": "items/0APU21xYhn2STUk9PVA", "owner": { "teamDrive": { "title": "test drive", "name": "teamDrives/0APU21xYhn2STUk9PVA" }, "domain": { "legacyId": "105870078053312191477", "name": "yagisanatode.com" }, "drive": { "name": "drives/0APU21xYhn2STUk9PVA", "title": "test drive" } }, "title": "test drive", "folder": { "type": "TEAM_DRIVE_ROOT" } }, "name": "teamDrives/0APU21xYhn2STUk9PVA" }, "drive": { "name": "drives/0APU21xYhn2STUk9PVA", "title": "test drive", "root": { "name": "items/0APU21xYhn2STUk9PVA", "folder": { "type": "TEAM_DRIVE_ROOT" }, "title": "test drive", "driveFolder": { "type": "SHARED_DRIVE_ROOT" }, "owner": { "teamDrive": { "title": "test drive", "name": "teamDrives/0APU21xYhn2STUk9PVA" }, "domain": { "name": "yagisanatode.com", "legacyId": "105870078053312191477" }, "drive": { "name": "drives/0APU21xYhn2STUk9PVA", "title": "test drive" } } } } } ], "actors": [ { "user": { "knownUser": { "isCurrentUser": true, "personName": "people/102444833385071164881" } } } ] } ] } |
Getting the Shared Drive creator’s unique id.
If you look down at the actors’ property on line 79 of the object above, you should see only one user, the creator of the shared drive. This will be under “user” > “knowUser” > “personName”.
As you can see, the creator’s email is not provided. We will need to find this in a moment, but first, we need to extract the user’s id from the personName
property.
const personName = activity.activities[0].actors[0].user.knownUser.personName
We won’t need the prepended “person/” in the personName value so let’s create a JavaScript substring of just the numerical id.
const accountId = personName.substring(7)
This will result in something like this:
102444833385071164881
Get the user’s details from the Google Admin Directory SDK
With the “users” unique numerical ID we can now use the Google Admin Directory SDK to access some details about the user.
At its most basic level, we can get a user’s details with:
AdminDirectory.Users.get(accountId)
Non-admin privileged users can still make use of the Admin Directory SDK. However, they will be limited to just the information that is publically available. For us, this is no problem, we only want the publically available primary email of our creator.
To ensure that users without admin privileges can run the code without error we need to add an object field to the second parameter of the get request changing the view type to domain public.
"viewType": "domain_public"
Next, we will also set the projection to “basic” to limit the amount of object data returned from the query.
"projection": "basic"
Weirdly, when a user with admin privileges runs code with a “domain public” view type it will result in an error. As such, we need to provide a “Try Catch” statement to handle the times admins run the code.
So, within the catch statement, we can add just the account id to the get method for the admins to access the data.
The resulting object will look a little like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
{ "emails": [ { "primary": true, "address": "tester@yagisanatode.com" } ], "etag": "\"CTyc505ppdmJR2motHVsU17kzItOkPo5vYViqlSF0rU/6jjFgzOiSrwVzg8F6YkHTKeloqI\"", "name": { "givenName": "tester", "familyName": "account", "fullName": "tester account" }, "kind": "admin#directory#user", "id": "102444833385071164881", "languages": [ { "preference": "preferred", "languageCode": "en-GB" } ], "primaryEmail": "tester@yagisanatode.com" } |
Retrieving the email address
Finally, we can collect the primary email of the user with the object path:
user.primaryEmail
Then we return that email back to be used by the function it was instantiated from.
Conclusion
While on the whole, this might be a little bit more of a convoluted process that first expected, the entire processing speed was relatively short.
Try and give this a run-through on your own and then try and get the creator emails of all the shared drives that you have access to by connecting it to the tutorial below:
https://yagisanatode.com/2021/07/26/get-a-list-of-google-shared-drives-by-id-and-name-in-google-apps-script/
I really like to hear how folk are using and adapting the code that I provide. It provides inspiration for me and the people reading the article. Please consider sharing your use cases in the comments below and subscribe (Top-right sidebar).
Need help with Google Workspace development?
My team of experts can help you with all of your needs, from custom app development to integrations and security. We have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.
Schedule a free consultation today to discuss your needs and get started or learn more about our services here.
~Yagi
Like this:
Like Loading...