gtm-setup
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGTM Setup - Technical Prerequisites
GTM 设置 - 技术前置条件
Automate the complete GTM API setup process, from installing dependencies to validating API access.
自动完成完整的GTM API设置流程,从依赖安装到API访问验证。
Workflow
工作流程
Phase 1: Prerequisites Check
阶段1:前置条件检查
Step 1.1: Check Node.js Project
Verify package.json exists:
- If missing → Error: "This must be run in a Node.js project"
- If exists → ContinueStep 1.2: Check for Existing Setup
Check for existing files:
- gtm-credentials.json → Already configured
- gtm-token.json → Already authorized
- gtm-config.json → Configuration exists
If all exist:
→ "GTM API already configured. Run validation to test connection."
→ Skip to Phase 6 (Validation)
If partial:
→ "Partial setup detected. Continuing from [step]..."步骤1.1:检查Node.js项目
Verify package.json exists:
- If missing → Error: "This must be run in a Node.js project"
- If exists → Continue步骤1.2:检查现有设置
Check for existing files:
- gtm-credentials.json → Already configured
- gtm-token.json → Already authorized
- gtm-config.json → Configuration exists
If all exist:
→ "GTM API already configured. Run validation to test connection."
→ Skip to Phase 6 (Validation)
If partial:
→ "Partial setup detected. Continuing from [step]..."Phase 2: Install googleapis
阶段2:安装googleapis
Step 2.1: Auto-Install Package
Run: npm install googleapis --save
Monitor output for:
✓ Success → Continue
✗ Error → Display error, suggest manual installationStep 2.2: Verify Installation
Check package.json dependencies:
- "googleapis": "^..." present → Success
- Missing → Retry or manual install步骤2.1:自动安装包
Run: npm install googleapis --save
Monitor output for:
✓ Success → Continue
✗ Error → Display error, suggest manual installation步骤2.2:验证安装
Check package.json dependencies:
- "googleapis": "^..." present → Success
- Missing → Retry or manual installPhase 3: Google Cloud Project Setup
阶段3:Google Cloud项目设置
Step 3.1: Guide Cloud Console Access
Present clickable URLs:
Step 1: Create/Select Google Cloud Project
→ https://console.cloud.google.com/projectcreate
Step 2: Enable Google Tag Manager API
→ https://console.cloud.google.com/apis/library/tagmanager.googleapis.com
Step 3: Create OAuth 2.0 Credentials
→ https://console.cloud.google.com/apis/credentials
Wait for user confirmation at each step.Step 3.2: OAuth Credential Configuration
Guide user through credential creation:
1. Click "Create Credentials" → "OAuth client ID"
2. Application type: "Desktop app"
3. Name: "GTM Automation Script"
4. Click "Create"
5. Download JSON file
Prompt: "Download the credentials JSON file and save it in your project root."Step 3.3: Save Credentials
Ask user for downloaded file path:
→ "Where did you save the credentials file?"
Options:
a) File is in project root → Look for oauth2.keys.json or similar
b) User provides path → Copy to gtm-credentials.json
c) User pastes content → Write to gtm-credentials.json
Validate JSON structure:
- Has "installed" or "web" key
- Has "client_id", "client_secret", "redirect_uris"
If invalid → Error with specific issue
If valid → Save as gtm-credentials.json步骤3.1:引导访问Cloud Console
Present clickable URLs:
Step 1: Create/Select Google Cloud Project
→ https://console.cloud.google.com/projectcreate
Step 2: Enable Google Tag Manager API
→ https://console.cloud.google.com/apis/library/tagmanager.googleapis.com
Step 3: Create OAuth 2.0 Credentials
→ https://console.cloud.google.com/apis/credentials
Wait for user confirmation at each step.步骤3.2:OAuth凭证配置
Guide user through credential creation:
1. Click "Create Credentials" → "OAuth client ID"
2. Application type: "Desktop app"
3. Name: "GTM Automation Script"
4. Click "Create"
5. Download JSON file
Prompt: "Download the credentials JSON file and save it in your project root."步骤3.3:保存凭证
Ask user for downloaded file path:
→ "Where did you save the credentials file?"
Options:
a) File is in project root → Look for oauth2.keys.json or similar
b) User provides path → Copy to gtm-credentials.json
c) User pastes content → Write to gtm-credentials.json
Validate JSON structure:
- Has "installed" or "web" key
- Has "client_id", "client_secret", "redirect_uris"
If invalid → Error with specific issue
If valid → Save as gtm-credentials.jsonPhase 4: GTM Account & Container Configuration
阶段4:GTM账户与容器配置
Step 4.1: Gather GTM Information
Guide user to find GTM details:
"Open Google Tag Manager: https://tagmanager.google.com"
Q1: What is your GTM Account ID?
→ Hint: In GTM, go to Admin. Account ID is shown at top (format: 1234567890)
Q2: What is your GTM Container ID?
→ Hint: In GTM, select container. Container ID shown at top (format: GTM-XXXXXX)
Validate inputs:
- Account ID: Must be numeric
- Container ID: Must start with "GTM-"Step 4.2: Create Configuration File
Generate gtm-config.json:
{
"accountId": "[user input]",
"containerId": "[user input]",
"containerPublicId": "[user input]"
}
Save to project root.Note: workspaceId is NOT stored in gtm-config.json. The gtm-implementation skill always resolves the active workspace dynamically via the GTM API. This prevents breakage after you publish a version in the GTM UI, which deletes and recreates the workspace.
步骤4.1:收集GTM信息
Guide user to find GTM details:
"Open Google Tag Manager: https://tagmanager.google.com"
Q1: What is your GTM Account ID?
→ Hint: In GTM, go to Admin. Account ID is shown at top (format: 1234567890)
Q2: What is your GTM Container ID?
→ Hint: In GTM, select container. Container ID shown at top (format: GTM-XXXXXX)
Validate inputs:
- Account ID: Must be numeric
- Container ID: Must start with "GTM-"步骤4.2:创建配置文件
Generate gtm-config.json:
{
"accountId": "[user input]",
"containerId": "[user input]",
"containerPublicId": "[user input]"
}
Save to project root.注意:workspaceId不会存储在gtm-config.json中。gtm-implementation技能会始终通过GTM API动态解析活动工作区。这可以避免在GTM UI中发布版本后工作区被删除导致的问题,因为发布后工作区会被删除并重新创建。
Phase 5: OAuth Authorization
阶段5:OAuth授权
Step 5.1: Generate Auth URL
Using googleapis library, generate OAuth consent URL.
Present to user:
"
=== Authorization Required ===
Open this URL in your browser to authorize access:
[Long Google OAuth URL]
This will:
1. Ask you to sign in to Google
2. Show permissions requested (Read/Write GTM access)
3. Redirect to a localhost URL with an authorization code
After authorizing, you'll see a page that says:
'The authentication flow has completed. You may close this window.'
Copy the FULL URL from your browser address bar.
"Step 5.2: Exchange Code for Token
Prompt: "Paste the full redirect URL here:"
Extract authorization code from URL:
- URL format: http://localhost/?code=XXXX&scope=...
- Parse 'code' parameter
Exchange code for access/refresh tokens using OAuth2 client.
Save tokens to gtm-token.json:
{
"access_token": "...",
"refresh_token": "...",
"scope": "...",
"token_type": "Bearer",
"expiry_date": 1234567890
}
Success message:
"✓ Authorization complete! Tokens saved to gtm-token.json"步骤5.1:生成授权URL
Using googleapis library, generate OAuth consent URL.
Present to user:
"
=== Authorization Required ===
Open this URL in your browser to authorize access:
[Long Google OAuth URL]
This will:
1. Ask you to sign in to Google
2. Show permissions requested (Read/Write GTM access)
3. Redirect to a localhost URL with an authorization code
After authorizing, you'll see a page that says:
'The authentication flow has completed. You may close this window.'
Copy the FULL URL from your browser address bar.
"步骤5.2:交换授权码获取令牌
Prompt: "Paste the full redirect URL here:"
Extract authorization code from URL:
- URL format: http://localhost/?code=XXXX&scope=...
- Parse 'code' parameter
Exchange code for access/refresh tokens using OAuth2 client.
Save tokens to gtm-token.json:
{
"access_token": "...",
"refresh_token": "...",
"scope": "...",
"token_type": "Bearer",
"expiry_date": 1234567890
}
Success message:
"✓ Authorization complete! Tokens saved to gtm-token.json"Phase 6: Validation & Testing
阶段6:验证与测试
Step 6.1: Test API Connection
Using saved credentials and token, make test API call:
GET /tagmanager/v2/accounts/{accountId}/containers/{containerId}
Expected responses:
✓ 200 OK → Success! Container details returned
✗ 401 Unauthorized → Token invalid, re-authorize
✗ 403 Forbidden → Missing permissions, check API enable
✗ 404 Not Found → Wrong account/container ID
✗ Other → Display error detailsStep 6.2: Verify Permissions
Check API response for required permissions:
Required GTM API scopes:
- tagmanager.edit.containers
- tagmanager.readonly
If missing scopes:
→ Error: "Insufficient permissions. Re-authorize with correct scopes."
→ Restart Phase 5Step 6.3: Final Confirmation
Display success summary:
"
=== GTM API Setup Complete ===
✓ googleapis installed
✓ OAuth credentials configured (gtm-credentials.json)
✓ Access token obtained (gtm-token.json)
✓ GTM configuration saved (gtm-config.json)
✓ API connection validated
Account: [accountId]
Container: [containerPublicId]
Files created:
- gtm-credentials.json (OAuth credentials)
- gtm-token.json (Access token - DO NOT commit to git)
- gtm-config.json (GTM account/container info)
Next steps:
→ Add gtm-token.json to .gitignore
→ Invoke gtm-implementation skill to implement tracking
Ready to implement tracking? Invoke gtm-implementation skill.
"步骤6.1:测试API连接
Using saved credentials and token, make test API call:
GET /tagmanager/v2/accounts/{accountId}/containers/{containerId}
Expected responses:
✓ 200 OK → Success! Container details returned
✗ 401 Unauthorized → Token invalid, re-authorize
✗ 403 Forbidden → Missing permissions, check API enable
✗ 404 Not Found → Wrong account/container ID
✗ Other → Display error details步骤6.2:验证权限
Check API response for required permissions:
Required GTM API scopes:
- tagmanager.edit.containers
- tagmanager.readonly
If missing scopes:
→ Error: "Insufficient permissions. Re-authorize with correct scopes."
→ Restart Phase 5步骤6.3:最终确认
Display success summary:
"
=== GTM API Setup Complete ===
✓ googleapis installed
✓ OAuth credentials configured (gtm-credentials.json)
✓ Access token obtained (gtm-token.json)
✓ GTM configuration saved (gtm-config.json)
✓ API connection validated
Account: [accountId]
Container: [containerPublicId]
Files created:
- gtm-credentials.json (OAuth credentials)
- gtm-token.json (Access token - DO NOT commit to git)
- gtm-config.json (GTM account/container info)
Next steps:
→ Add gtm-token.json to .gitignore
→ Invoke gtm-implementation skill to implement tracking
Ready to implement tracking? Invoke gtm-implementation skill.
"Scripts
脚本
Use the following scripts for automated steps:
使用以下脚本完成自动化步骤:
scripts/install-googleapis.js
scripts/install-googleapis.js
javascript
// Auto-install googleapis package
const { execSync } = require('child_process');
try {
console.log('Installing googleapis...');
execSync('npm install googleapis --save', { stdio: 'inherit' });
console.log('✓ googleapis installed successfully');
} catch (error) {
console.error('✗ Installation failed:', error.message);
process.exit(1);
}javascript
// Auto-install googleapis package
const { execSync } = require('child_process');
try {
console.log('Installing googleapis...');
execSync('npm install googleapis --save', { stdio: 'inherit' });
console.log('✓ googleapis installed successfully');
} catch (error) {
console.error('✗ Installation failed:', error.message);
process.exit(1);
}scripts/validate-prerequisites.js
scripts/validate-prerequisites.js
javascript
// Validate existing setup files
const fs = require('fs');
const path = require('path');
const files = {
'package.json': { required: true, description: 'Node.js project' },
'gtm-credentials.json': { required: false, description: 'OAuth credentials' },
'gtm-token.json': { required: false, description: 'Access token' },
'gtm-config.json': { required: false, description: 'GTM configuration' }
};
console.log('Validating prerequisites...\n');
let allValid = true;
let setupStatus = {
credentials: false,
token: false,
config: false
};
for (const [filename, config] of Object.entries(files)) {
const exists = fs.existsSync(path.join(process.cwd(), filename));
if (filename === 'gtm-credentials.json' && exists) setupStatus.credentials = true;
if (filename === 'gtm-token.json' && exists) setupStatus.token = true;
if (filename === 'gtm-config.json' && exists) setupStatus.config = true;
const status = exists ? '✓' : (config.required ? '✗' : '○');
console.log(`${status} ${filename} - ${config.description}`);
if (config.required && !exists) {
allValid = false;
}
}
console.log('\nSetup status:');
if (setupStatus.credentials && setupStatus.token && setupStatus.config) {
console.log('✓ Complete setup detected');
console.log('→ Run test-connection.js to validate');
} else if (setupStatus.credentials || setupStatus.token || setupStatus.config) {
console.log('○ Partial setup detected');
if (!setupStatus.credentials) console.log(' Missing: OAuth credentials');
if (!setupStatus.token) console.log(' Missing: Access token');
if (!setupStatus.config) console.log(' Missing: GTM configuration');
} else {
console.log('○ No setup detected');
console.log('→ Start from Phase 3 (Google Cloud setup)');
}
process.exit(allValid ? 0 : 1);javascript
// Validate existing setup files
const fs = require('fs');
const path = require('path');
const files = {
'package.json': { required: true, description: 'Node.js project' },
'gtm-credentials.json': { required: false, description: 'OAuth credentials' },
'gtm-token.json': { required: false, description: 'Access token' },
'gtm-config.json': { required: false, description: 'GTM configuration' }
};
console.log('Validating prerequisites...\n');
let allValid = true;
let setupStatus = {
credentials: false,
token: false,
config: false
};
for (const [filename, config] of Object.entries(files)) {
const exists = fs.existsSync(path.join(process.cwd(), filename));
if (filename === 'gtm-credentials.json' && exists) setupStatus.credentials = true;
if (filename === 'gtm-token.json' && exists) setupStatus.token = true;
if (filename === 'gtm-config.json' && exists) setupStatus.config = true;
const status = exists ? '✓' : (config.required ? '✗' : '○');
console.log(`${status} ${filename} - ${config.description}`);
if (config.required && !exists) {
allValid = false;
}
}
console.log('\nSetup status:');
if (setupStatus.credentials && setupStatus.token && setupStatus.config) {
console.log('✓ Complete setup detected');
console.log('→ Run test-connection.js to validate');
} else if (setupStatus.credentials || setupStatus.token || setupStatus.config) {
console.log('○ Partial setup detected');
if (!setupStatus.credentials) console.log(' Missing: OAuth credentials');
if (!setupStatus.token) console.log(' Missing: Access token');
if (!setupStatus.config) console.log(' Missing: GTM configuration');
} else {
console.log('○ No setup detected');
console.log('→ Start from Phase 3 (Google Cloud setup)');
}
process.exit(allValid ? 0 : 1);scripts/oauth-authorize.js
scripts/oauth-authorize.js
javascript
// OAuth authorization flow
const { google } = require('googleapis');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const SCOPES = ['https://www.googleapis.com/auth/tagmanager.edit.containers'];
const TOKEN_PATH = path.join(process.cwd(), 'gtm-token.json');
const CREDENTIALS_PATH = path.join(process.cwd(), 'gtm-credentials.json');
// Load credentials
const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
const { client_secret, client_id, redirect_uris } = credentials.installed || credentials.web;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
// Generate auth URL
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('\n=== GTM API Authorization ===\n');
console.log('Open this URL in your browser to authorize:\n');
console.log(authUrl);
console.log('\nAfter authorization, copy the full redirect URL from your browser.\n');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Paste the redirect URL here: ', (redirectUrl) => {
rl.close();
// Extract code from URL
const url = new URL(redirectUrl);
const code = url.searchParams.get('code');
if (!code) {
console.error('✗ No authorization code found in URL');
process.exit(1);
}
// Exchange code for token
oAuth2Client.getToken(code, (err, token) => {
if (err) {
console.error('✗ Error retrieving access token:', err);
process.exit(1);
}
// Save token
fs.writeFileSync(TOKEN_PATH, JSON.stringify(token, null, 2));
console.log('\n✓ Token saved to', TOKEN_PATH);
console.log('\n=== Authorization Complete ===\n');
console.log('You can now use the GTM API.');
console.log('\nIMPORTANT: Add gtm-token.json to .gitignore\n');
});
});javascript
// OAuth authorization flow
const { google } = require('googleapis');
const fs = require('fs');
const path = require('path');
const readline = require('readline');
const SCOPES = ['https://www.googleapis.com/auth/tagmanager.edit.containers'];
const TOKEN_PATH = path.join(process.cwd(), 'gtm-token.json');
const CREDENTIALS_PATH = path.join(process.cwd(), 'gtm-credentials.json');
// Load credentials
const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
const { client_secret, client_id, redirect_uris } = credentials.installed || credentials.web;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
// Generate auth URL
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('\n=== GTM API Authorization ===\n');
console.log('Open this URL in your browser to authorize:\n');
console.log(authUrl);
console.log('\nAfter authorization, copy the full redirect URL from your browser.\n');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Paste the redirect URL here: ', (redirectUrl) => {
rl.close();
// Extract code from URL
const url = new URL(redirectUrl);
const code = url.searchParams.get('code');
if (!code) {
console.error('✗ No authorization code found in URL');
process.exit(1);
}
// Exchange code for token
oAuth2Client.getToken(code, (err, token) => {
if (err) {
console.error('✗ Error retrieving access token:', err);
process.exit(1);
}
// Save token
fs.writeFileSync(TOKEN_PATH, JSON.stringify(token, null, 2));
console.log('\n✓ Token saved to', TOKEN_PATH);
console.log('\n=== Authorization Complete ===\n');
console.log('You can now use the GTM API.');
console.log('\nIMPORTANT: Add gtm-token.json to .gitignore\n');
});
});scripts/test-connection.js
scripts/test-connection.js
javascript
// Test GTM API connection
const { google } = require('googleapis');
const fs = require('fs');
const path = require('path');
const TOKEN_PATH = path.join(process.cwd(), 'gtm-token.json');
const CREDENTIALS_PATH = path.join(process.cwd(), 'gtm-credentials.json');
const CONFIG_PATH = path.join(process.cwd(), 'gtm-config.json');
// Check files exist
if (!fs.existsSync(CREDENTIALS_PATH)) {
console.error('✗ gtm-credentials.json not found');
process.exit(1);
}
if (!fs.existsSync(TOKEN_PATH)) {
console.error('✗ gtm-token.json not found. Run oauth-authorize.js first.');
process.exit(1);
}
if (!fs.existsSync(CONFIG_PATH)) {
console.error('✗ gtm-config.json not found');
process.exit(1);
}
// Load files
const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
const token = JSON.parse(fs.readFileSync(TOKEN_PATH, 'utf8'));
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
const { client_secret, client_id, redirect_uris } = credentials.installed || credentials.web;
// Create OAuth client
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
oAuth2Client.setCredentials(token);
// Create GTM client
const tagmanager = google.tagmanager({ version: 'v2', auth: oAuth2Client });
console.log('\n=== Testing GTM API Connection ===\n');
console.log(`Account ID: ${config.accountId}`);
console.log(`Container ID: ${config.containerPublicId}\n`);
// Test API call
const path_url = `accounts/${config.accountId}/containers/${config.containerId}`;
tagmanager.accounts.containers.get({ path: path_url })
.then(response => {
console.log('✓ Connection successful!\n');
console.log('Container details:');
console.log(` Name: ${response.data.name}`);
console.log(` Public ID: ${response.data.publicId}`);
console.log(` Usage Context: ${response.data.usageContext.join(', ')}\n`);
console.log('=== Setup Verified ===\n');
console.log('Ready to use GTM API!\n');
})
.catch(error => {
console.error('✗ Connection failed\n');
if (error.code === 401) {
console.error('Error: Unauthorized (401)');
console.error('→ Token may be expired. Run oauth-authorize.js again.\n');
} else if (error.code === 403) {
console.error('Error: Forbidden (403)');
console.error('→ Check that GTM API is enabled in Google Cloud Console.\n');
} else if (error.code === 404) {
console.error('Error: Not Found (404)');
console.error('→ Check account ID and container ID in gtm-config.json.\n');
} else {
console.error('Error:', error.message, '\n');
}
process.exit(1);
});javascript
// Test GTM API connection
const { google } = require('googleapis');
const fs = require('fs');
const path = require('path');
const TOKEN_PATH = path.join(process.cwd(), 'gtm-token.json');
const CREDENTIALS_PATH = path.join(process.cwd(), 'gtm-credentials.json');
const CONFIG_PATH = path.join(process.cwd(), 'gtm-config.json');
// Check files exist
if (!fs.existsSync(CREDENTIALS_PATH)) {
console.error('✗ gtm-credentials.json not found');
process.exit(1);
}
if (!fs.existsSync(TOKEN_PATH)) {
console.error('✗ gtm-token.json not found. Run oauth-authorize.js first.');
process.exit(1);
}
if (!fs.existsSync(CONFIG_PATH)) {
console.error('✗ gtm-config.json not found');
process.exit(1);
}
// Load files
const credentials = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, 'utf8'));
const token = JSON.parse(fs.readFileSync(TOKEN_PATH, 'utf8'));
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8'));
const { client_secret, client_id, redirect_uris } = credentials.installed || credentials.web;
// Create OAuth client
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);
oAuth2Client.setCredentials(token);
// Create GTM client
const tagmanager = google.tagmanager({ version: 'v2', auth: oAuth2Client });
console.log('\n=== Testing GTM API Connection ===\n');
console.log(`Account ID: ${config.accountId}`);
console.log(`Container ID: ${config.containerPublicId}\n`);
// Test API call
const path_url = `accounts/${config.accountId}/containers/${config.containerId}`;
tagmanager.accounts.containers.get({ path: path_url })
.then(response => {
console.log('✓ Connection successful!\n');
console.log('Container details:');
console.log(` Name: ${response.data.name}`);
console.log(` Public ID: ${response.data.publicId}`);
console.log(` Usage Context: ${response.data.usageContext.join(', ')}\n`);
console.log('=== Setup Verified ===\n');
console.log('Ready to use GTM API!\n');
})
.catch(error => {
console.error('✗ Connection failed\n');
if (error.code === 401) {
console.error('Error: Unauthorized (401)');
console.error('→ Token may be expired. Run oauth-authorize.js again.\n');
} else if (error.code === 403) {
console.error('Error: Forbidden (403)');
console.error('→ Check that GTM API is enabled in Google Cloud Console.\n');
} else if (error.code === 404) {
console.error('Error: Not Found (404)');
console.error('→ Check account ID and container ID in gtm-config.json.\n');
} else {
console.error('Error:', error.message, '\n');
}
process.exit(1);
});References
参考资料
- - Detailed Google Cloud Console setup guide with screenshots
references/google-cloud-setup.md
- - 带截图的详细Google Cloud Console设置指南
references/google-cloud-setup.md
Important Guidelines
重要指南
Security Best Practices
安全最佳实践
-
Never commit tokens:
- Add to
gtm-token.json.gitignore - Tokens contain sensitive access credentials
- Add
-
Credentials file security:
- can be committed (contains no secrets for Desktop app type)
gtm-credentials.json - But recommend adding to for extra security
.gitignore
-
Token refresh:
- Tokens expire after 1 hour
- Refresh token (included) allows automatic renewal
- googleapis handles refresh automatically
-
切勿提交令牌:
- 将添加到
gtm-token.json.gitignore - 令牌包含敏感的访问凭证
- 将
-
凭证文件安全:
- 可以提交到版本控制(桌面应用类型的凭证不包含机密信息)
gtm-credentials.json - 但建议添加到以提升安全性
.gitignore
-
令牌刷新:
- 访问令牌会在1小时后过期
- 包含的刷新令牌允许自动续期
- googleapis库会自动处理令牌刷新
Common Issues
常见问题
Issue: "googleapis not found"
→ Solution: Run
npm install googleapis --saveIssue: "Invalid redirect URI"
→ Solution: Ensure OAuth client type is "Desktop app", not "Web application"
Issue: "403 Forbidden"
→ Solution: Enable GTM API in Google Cloud Console
Issue: "404 Not Found"
→ Solution: Verify account ID and container ID are correct
Issue: "Token expired"
→ Solution: Run oauth-authorize.js again to get new token
Issue: "Workspace not found" / skill creates a new workspace unexpectedly
→ Cause: GTM deletes workspaces after publishing. A stored workspace ID becomes stale.
→ Solution: The skill now resolves workspace dynamically. No action needed.
问题:"googleapis not found"
→ 解决方案:运行
npm install googleapis --save问题:"Invalid redirect URI"
→ 解决方案:确保OAuth客户端类型为“Desktop app”,而非“Web application”
问题:"403 Forbidden"
→ 解决方案:在Google Cloud Console中启用GTM API
问题:"404 Not Found"
→ 解决方案:验证账户ID和容器ID是否正确
问题:"Token expired"
→ 解决方案:重新运行oauth-authorize.js以获取新令牌
问题:"Workspace not found" / 技能意外创建新工作区
→ 原因:GTM在发布后会删除工作区,存储的工作区ID会失效
→ 解决方案:该技能现在会动态解析工作区,无需任何操作
Testing
测试
After setup, verify with:
bash
node scripts/test-connection.jsExpected output:
✓ Connection successful!
Container details:
Name: My Website
Public ID: GTM-XXXXXX
Usage Context: web
=== Setup Verified ===设置完成后,运行以下命令验证:
bash
node scripts/test-connection.js预期输出:
✓ Connection successful!
Container details:
Name: My Website
Public ID: GTM-XXXXXX
Usage Context: web
=== Setup Verified ===Execution Checklist
执行检查清单
- package.json exists (Node.js project)
- googleapis installed
- Google Cloud project created
- GTM API enabled
- OAuth credentials created and downloaded
- gtm-credentials.json saved
- GTM account ID obtained
- GTM container ID obtained
- gtm-config.json created
- OAuth authorization completed
- gtm-token.json saved
- API connection tested successfully
- gtm-token.json added to .gitignore
- package.json存在(Node.js项目)
- googleapis已安装
- Google Cloud项目已创建
- GTM API已启用
- OAuth凭证已创建并下载
- gtm-credentials.json已保存
- GTM账户ID已获取
- GTM容器ID已获取
- gtm-config.json已创建
- OAuth授权已完成
- gtm-token.json已保存
- API连接测试成功
- gtm-token.json已添加到.gitignore
Supporting Files
支持文件
- - Example setup session showing each phase output and files created
examples/sample.md
- - 展示每个阶段输出和创建文件的示例设置会话
examples/sample.md
Output Files
输出文件
- gtm-credentials.json - OAuth 2.0 client credentials
- gtm-token.json - Access token and refresh token (SENSITIVE)
- gtm-config.json - GTM account and container configuration
- gtm-credentials.json - OAuth 2.0客户端凭证
- gtm-token.json - 访问令牌和刷新令牌(敏感信息)
- gtm-config.json - GTM账户和容器配置
Handoff
交接
After successful setup:
✓ GTM API configured and validated
Next step: Invoke gtm-implementation skill to:
- Implement dataLayer events in your code
- Create GTM variables, triggers, and tags via API
Ready to implement? Invoke gtm-implementation skill.设置成功后:
✓ GTM API已配置并验证
下一步:调用gtm-implementation技能以:
- 在代码中实现dataLayer事件
- 通过API创建GTM变量、触发器和标签
准备好开始实现了吗?调用gtm-implementation技能。Common Questions
常见问题
Q: Can I use the same credentials for multiple projects?
A: Yes. Copy gtm-credentials.json to other projects. Each project needs its own token (gtm-token.json).
Q: What if I have multiple GTM containers?
A: Run setup for each container separately. Create different gtm-config.json files or use different project directories.
Q: Do I need a Google Cloud billing account?
A: No. GTM API is free to use. No billing account required.
Q: Can I revoke access later?
A: Yes. Go to https://myaccount.google.com/permissions and revoke access to "GTM Automation Script".
Q: What scopes does this request?
A: - Read and write access to GTM containers. This allows creating/updating variables, triggers, tags.
tagmanager.edit.containers问:我可以在多个项目中使用相同的凭证吗?
答:可以。将gtm-credentials.json复制到其他项目即可。每个项目需要自己的令牌(gtm-token.json)。
问:如果我有多个GTM容器怎么办?
答:为每个容器单独运行设置流程。可以创建不同的gtm-config.json文件或使用不同的项目目录。
问:我需要Google Cloud计费账户吗?
答:不需要。GTM API是免费使用的,无需计费账户。
问:我以后可以撤销访问权限吗?
答:可以。访问https://myaccount.google.com/permissions并撤销对“GTM Automation Script”的访问权限。
问:该技能请求哪些权限范围?
答: - 对GTM容器的读写权限。这允许创建/更新变量、触发器和标签。
tagmanager.edit.containers