Open tongdatarunsdeep opened 3 years ago
Hi @tongdatarunsdeep,
Apologies if I've misunderstood the issue; feel free to clear up if necessary.
I've been able to run this code successfully below. Before running the code, I've set GOOGLE_APPLICATION_CREDENTIALS
to my service account (json) file.
const {google} = require('googleapis');
const tagmanager = google.tagmanager('v2');
async function main() {
const auth = new google.auth.GoogleAuth({
// Scopes can be specified either as an array or as a single, space-delimited string.
scopes: ['https://www.googleapis.com/auth/tagmanager.edit.containers'],
});
// Acquire an auth client, and bind it to all future calls
const authClient = await auth.getClient();
google.options({auth: authClient});
// Do the magic
const res = await tagmanager.accounts.containers.workspaces.variables.update({
// When provided, this fingerprint must match the fingerprint of the variable in storage.
fingerprint: 'placeholder-value',
// GTM Variable's API relative path. Example: accounts/{account_id\}/containers/{container_id\}/workspaces/{workspace_id\}/variables/{variable_id\}
path:
'accounts/my-account/containers/my-container/workspaces/my-workspace/variables/my-variable',
// Request body metadata
requestBody: {
},
});
console.log(res.data);
}
main().catch(e => {
console.error(e);
throw e;
});
Please make sure the service account has the correct permissions to make these changes.
Hi @sofisl,
I could run the code in my local environment to generate an authentication token, the issue is the token then get rejected when using it to access tagmanager.accounts.containers.workspaces.variables.update() or .create() functions.
Note that the update/create function works for other variable types except for jsm variable.
I have no issues create or update folders, triggers and non jsm variables (eg, v or j variables).
Could you please try to run .create() for a jsm variable?
For example: when I'm using the following code to update a dataLayer variable (type: 'v') and a custom javascript variable (type: 'jsm'). The only change is to update variableID.
let variableInfo = await tagmanager.accounts.containers.workspaces.variables.get({
path: `accounts/${accountID}/containers/${targetGTM}/workspaces/1/variables/${variableID}`
});
let resource = {
name: `${variableInfo.data.name}_copy`,
type: variableInfo.data.type,
parameter: variableInfo.data.parameter
}
console.log(resource)
let updateVariable = await tagmanager.accounts.containers.workspaces.variables.update({
path: `accounts/${accountID}/containers/${targetGTM}/workspaces/1/variables/${variableID}`,
resource: resource
});
console.log(updateVariable.status)
return updateVariable;
}
I get 200 for the dataLayer variable
{
name: 'dataLayer_variable_copy',
type: 'v',
parameter: [
{ type: 'integer', key: 'dataLayerVersion', value: '2' },
{ type: 'boolean', key: 'setDefaultValue', value: 'false' },
{ type: 'template', key: 'name', value: 'data.state' }
]
}
200
But 404 for custom javascript one
user@C02ZWBRAMD6M gtm-test % node test.js
{
name: 'cjs_variable_copy',
type: 'jsm',
parameter: [
{
type: 'template',
key: 'javascript',
value: 'function() {return}'
}
]
}
/Users/user/drd/gtm-test/node_modules/gaxios/build/src/gaxios.js:113
throw new common_1.GaxiosError(`Request failed with status code ${translatedResponse.status}`, opts, translatedResponse);
^
GaxiosError: Not found or permission denied.
at Gaxios._request (/Users/user/drd/gtm-test/node_modules/gaxios/build/src/gaxios.js:113:23)
at processTicksAndRejections (node:internal/process/task_queues:94:5)
at async JWT.requestAsync (/Users/user/drd/gtm-test/node_modules/google-auth-library/build/src/auth/oauth2client.js:344:18)
at async test (/Users/user/drd/gtm-test/test.js:217:22) {
response: {
config: {
url: 'https://tagmanager.googleapis.com/tagmanager/v2/accounts/23565264/containers/41163836/workspaces/1/variables/178',
method: 'PUT',
userAgentDirectives: [
{
product: 'google-api-nodejs-client',
version: '4.4.3',
comment: 'gzip'
}
],
paramsSerializer: [Function (anonymous)],
data: {
name: 'cjs_variable_copy',
type: 'jsm',
parameter: [
{
type: 'template',
key: 'javascript',
value: 'function() {return}'
}
]
},
headers: {
'x-goog-api-client': 'gdcl/4.4.3 gl-node/15.8.0 auth/6.1.6',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/4.4.3 (gzip)',
Authorization: 'Bearer ya29.c.KqMB9gdjqKdaJ6xr5S1m1BLFzi0qPFEtPKcPCKiphIobCRZS0nz7mn8tVMn6SbOEB1hNNZ9UZkF7UVeJnd3Nq-xjASb9030Sn-ubQKdhZvHp2deCB9JEC4K8sf7fmnnr_UBRrhHQcjNAkFucd0GYnTJZIWDugYZw1E3U4qb2WpYmZ-cOx_BPs7JgL6Ku_2QS21dUOAmXYNAJtTqewwWvM4sFNDCLNA',
'Content-Type': 'application/json',
Accept: 'application/json'
},
params: {},
validateStatus: [Function (anonymous)],
retry: true,
body: '{"name":"cjs_variable_copy","type":"jsm","parameter":[{"type":"template","key":"javascript","value":"function() {return}"}]}',
responseType: 'json',
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [ 'GET', 'HEAD', 'PUT', 'OPTIONS', 'DELETE' ],
noResponseRetries: 2,
statusCodesToRetry: [ [ 100, 199 ], [ 429, 429 ], [ 500, 599 ] ]
}
},
data: {
error: {
code: 404,
message: 'Not found or permission denied.',
errors: [
{
message: 'Not found or permission denied.',
domain: 'global',
reason: 'notFound'
}
],
status: 'NOT_FOUND'
}
},
headers: {
'alt-svc': 'h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"',
'cache-control': 'private',
connection: 'close',
'content-encoding': 'gzip',
'content-type': 'application/json; charset=UTF-8',
date: 'Wed, 10 Mar 2021 06:08:11 GMT',
server: 'ESF',
'transfer-encoding': 'chunked',
vary: 'Origin, X-Origin, Referer',
'x-content-type-options': 'nosniff',
'x-frame-options': 'SAMEORIGIN',
'x-xss-protection': '0'
},
status: 404,
statusText: 'Not Found',
request: {
responseURL: 'https://tagmanager.googleapis.com/tagmanager/v2/accounts/23565264/containers/41163836/workspaces/1/variables/178'
}
},
config: {
url: 'https://tagmanager.googleapis.com/tagmanager/v2/accounts/23565264/containers/41163836/workspaces/1/variables/178',
method: 'PUT',
userAgentDirectives: [
{
product: 'google-api-nodejs-client',
version: '4.4.3',
comment: 'gzip'
}
],
paramsSerializer: [Function (anonymous)],
data: {
name: 'cjs_variable_copy',
type: 'jsm',
parameter: [
{
type: 'template',
key: 'javascript',
value: 'function() {return}'
}
]
},
headers: {
'x-goog-api-client': 'gdcl/4.4.3 gl-node/15.8.0 auth/6.1.6',
'Accept-Encoding': 'gzip',
'User-Agent': 'google-api-nodejs-client/4.4.3 (gzip)',
Authorization: 'Bearer ya29.c.KqMB9gdjqKdaJ6xr5S1m1BLFzi0qPFEtPKcPCKiphIobCRZS0nz7mn8tVMn6SbOEB1hNNZ9UZkF7UVeJnd3Nq-xjASb9030Sn-ubQKdhZvHp2deCB9JEC4K8sf7fmnnr_UBRrhHQcjNAkFucd0GYnTJZIWDugYZw1E3U4qb2WpYmZ-cOx_BPs7JgL6Ku_2QS21dUOAmXYNAJtTqewwWvM4sFNDCLNA',
'Content-Type': 'application/json',
Accept: 'application/json'
},
params: {},
validateStatus: [Function (anonymous)],
retry: true,
body: '{"name":"cjs_variable_copy","type":"jsm","parameter":[{"type":"template","key":"javascript","value":"function() {return}"}]}',
responseType: 'json',
retryConfig: {
currentRetryAttempt: 0,
retry: 3,
httpMethodsToRetry: [ 'GET', 'HEAD', 'PUT', 'OPTIONS', 'DELETE' ],
noResponseRetries: 2,
statusCodesToRetry: [ [ 100, 199 ], [ 429, 429 ], [ 500, 599 ] ]
}
},
code: 404,
errors: [
{
message: 'Not found or permission denied.',
domain: 'global',
reason: 'notFound'
}
]
}
HI @tongdatarunsdeep, do you have this scope set? https://www.googleapis.com/auth/tagmanager.edit.containers
If you're using the oAuth flow, you may need to revoke and regrant access to your app for those scopes: https://myaccount.google.com/permissions
Hi @sofisl,
Yes, I have the scope https://www.googleapis.com/auth/tagmanager.edit.containers. I have also tried to add other different scopes but was getting the same error. If the issue is caused by the scope, it shouldn't work for other types of variables?
Currently I'm using:
const auth = new google.auth.GoogleAuth({
scopes: ['https://www.googleapis.com/auth/tagmanager.edit.containers','https://www.googleapis.com/auth/tagmanager.readonly','https://www.googleapis.com/auth/tagmanager.publish']
});
const authClient = await auth.getClient();
const tagmanager = google.tagmanager({
version: 'v2',
auth: authClient
});
I'm not using OAuth flow but a service account auth (the function will run in google cloud function, so I can't use OAuth). I can send you the credentials.json file if needed.
I'm having a similar issue with the GTM API using a service account where I can't authenticate at all. I'm currently getting 401 errors (GaxiosError: Login Required). Code below.
const {google} = require('googleapis');
const scopes = [
'https://www.googleapis.com/auth/tagmanager.readonly',
'https://www.googleapis.com/auth/tagmanager.manage.accounts',
'https://www.googleapis.com/auth/tagmanager.edit.containers',
'https://www.googleapis.com/auth/tagmanager.delete.containers',
'https://www.googleapis.com/auth/tagmanager.edit.containerversions',
'https://www.googleapis.com/auth/tagmanager.manage.users',
'https://www.googleapis.com/auth/tagmanager.publish'
];
export async function gtmAuthenticate() {
try {
const auth = new google.auth.GoogleAuth({
scopes: scopes,
});
const authClient = await auth.getClient();
google.tagmanager({
version: 'v2',
auth: authClient
});
} catch (err) {
console.log(err);
}
}
I'm having a similar issue with the GTM API using a service account where I can't authenticate at all. I'm currently getting 401 errors (GaxiosError: Login Required). Code below.
const {google} = require('googleapis'); const scopes = [ 'https://www.googleapis.com/auth/tagmanager.readonly', 'https://www.googleapis.com/auth/tagmanager.manage.accounts', 'https://www.googleapis.com/auth/tagmanager.edit.containers', 'https://www.googleapis.com/auth/tagmanager.delete.containers', 'https://www.googleapis.com/auth/tagmanager.edit.containerversions', 'https://www.googleapis.com/auth/tagmanager.manage.users', 'https://www.googleapis.com/auth/tagmanager.publish' ]; export async function gtmAuthenticate() { try { const auth = new google.auth.GoogleAuth({ scopes: scopes, }); const authClient = await auth.getClient(); google.tagmanager({ version: 'v2', auth: authClient }); } catch (err) { console.log(err); } }
Hi @evan-rosa, I had that issue at the beginning as well. Have you tried to run
gcloud auth application-default login
in the console?
@tongdatarunsdeep - Yes, I authenticated with gcloud but still the same error when running the script.
@tongdatarunsdeep - Just following up, any specific reason I'm still getting a 401 error? Any suggestions?
Following up on my issue with 401 errors, I was able to resolve the issue by implementing my auth on each GTM component rather than trying to authenticate globally for all of my code.
@tongdatarunsdeep I would be surprised if this was specifically an issue with the npm module itself, rather something missing on the service account or permission set. Honestly, we're not experts specifically on tagmanager, and I suspect you'd have better luck on Stack Overflow for this part: https://stackoverflow.com/questions/tagged/google-tag-manager
If you have a support contract with Google that can get you in front of support folks who can specifically look at your service account, that's also a great approach.
I’m using a service account to access tagmanager API but getting 404 error for some functions.
After authorising the service account by using credentials.json file, I could access most of the tagmanager API v2 functions except for variable update for custom javascript(jsm) type variable.
The code returned 404 permission denied error. The same code works for other variable types, eg, DataLayer (v) variable (returns 200 code).
The service account has admin access at the GTM account level, and publish access at the container level. (The container itself was created by the same service account).
I have tried the same configuration via API explorer, it uses OAth2 flow to auth my personal email address(has the same access level at account and container level as the service account) and returned 200. I then copied the Auth token generated by the API explorer page and forced the node module oauth2client.js to use this token on /node_modules/google-auth-library/build/src/auth/oauth2client.js:337. from:
to:
After this, the custom javascript variable can be updated by my code. which means the issue is caused by the auth token generated for the service account.
Error log:
Auth function used in code