You would think that accessing the name or email of the creator of a Google Drive file would be super easy. In the Google Drive display, there is already a provision for the creation date and the name of the file’s owner, and in the Shared Drive, we can see the creator’s name. It is hardly a security issue.
We can even fairly easily retrieve the details of the user who last modified the file using the Drive API (Google Apps Script Advanced Sheets Service) with the lastModifyingUser property of the returned file object, which gives us a happy little list of User properties that include the modifying user’s display name and email.
With the file creator, all we want is similar information, and it would be generated once and remain immutable. Seems like a no-brainer.
So why is it so hard to get the file creator details in Google Drive programmatically?
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:
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:
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:
Google Drive Activity Create filter
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.
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:
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:
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?
Go something to solve bigger than Chat GPT?
I can help you with all of your Google Workspace development needs, from custom app development to integrations and security. I have a proven track record of success in helping businesses of all sizes get the most out of Google Workspace.