### 10.1 Autenticación (OAuth 2.0)
Setup inicial (se hace una sola vez):
`bash
python3 -m venv /tmp/gsc_auth
source /tmp/gsc_auth/bin/activate
pip install google-auth-oauthlib google-auth-httplib2 googleapiclient
python3 << 'EOF'
from google_auth_oauthlib.flow import InstalledAppFlow
import os, json
SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']
CRED_FILE = os.path.expanduser('~/.gsc/credentials.json')
TOKEN_FILE = os.path.expanduser('~/.gsc/token.json')
flow = InstalledAppFlow.from_client_secrets_file(CRED_FILE, SCOPES)
creds = flow.run_local_server(port=8080)
with open(TOKEN_FILE, 'w') as f:
json.dump({
'token': creds.token,
'refresh_token': creds.refresh_token,
'client_id': creds.client_id,
'client_secret': creds.client_secret,
'token_uri': creds.token_uri
}, f)
print("✅ Token guardado en ~/.gsc/token.json")
EOF
`
Refrescar el token (script reusable):
Guardar como ~/.gsc/refresh_token.py:
`python
#!/usr/bin/env python3
import json, os
from google.oauth2.credentials import Credentials
TOKEN_FILE = os.path.expanduser('~/.gsc/token.json')
def get_token():
with open(TOKEN_FILE) as f:
data = json.load(f)
creds = Credentials.from_authorized_user_info(data)
if creds.expired:
creds.refresh(Request())
with open(TOKEN_FILE, 'w') as f:
json.dump({
'token': creds.token,
'refresh_token': creds.refresh_token,
'client_id': creds.client_id,
'client_secret': creds.client_secret,
'token_uri': creds.token_uri
}, f)
return creds.token
if __name__ == '__main__':
print(get_token())
`
Generar token para usar con curl:
`bash
python3 ~/.gsc/refresh_token.py > /tmp/gsc_token.txt
curl -s \
"https://www.googleapis.com/webmasters/v3/sites" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
| jq '.siteEntry[].siteUrl'
`
### 10.2 Queries Más Útiles
#### 10.2.1 Listar todas las propiedades GSC del usuario
`bash
curl -s \
"https://www.googleapis.com/webmasters/v3/sites" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
| jq '.'
`
#### 10.2.2 Performance — Top 100 queries de los últimos 28 días
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["query"],
"rowLimit": 100,
"orderBy": [{"field": "clicks", "order": "descending"}]
}' | jq '.rows[] | {query: .keys[0], clicks: .clicks, impressions: .impressions, ctr: .ctr, position: .position}'
`
#### 10.2.3 Performance — Top 100 páginas de los últimos 28 días
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["page"],
"rowLimit": 100,
"orderBy": [{"field": "clicks", "order": "descending"}]
}' | jq '.rows[] | {page: .keys[0], clicks: .clicks, impressions: .impressions, ctr: .ctr, position: .position}'
`
#### 10.2.4 Performance por query + página (detectar canibalización)
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["query","page"],
"rowLimit": 5000,
"orderBy": [{"field": "clicks", "order": "descending"}]
}'
`
#### 10.2.5 Performance por fecha (tendencia diaria)
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["date"],
"rowLimit": 100
}' | jq '.rows[] | {date: .keys[0], clicks: .clicks, impressions: .impressions}'
`
#### 10.2.6 Performance por país
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["country"],
"rowLimit": 50,
"orderBy": [{"field": "clicks", "order": "descending"}]
}' | jq '.rows[] | {country: .keys[0], clicks: .clicks, impressions: .impressions, ctr: .ctr}'
`
#### 10.2.7 Performance por dispositivo
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["device"],
"rowLimit": 10
}' | jq '.rows[] | {device: .keys[0], clicks: .clicks, impressions: .impressions, ctr: .ctr, position: .position}'
`
#### 10.2.8 Performance por query + país (para ShoppingDigital Argentina)
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.shoppingdigital.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["query","country"],
"dimensionFilterGroups": [{
"filters": [{"dimension": "country", "operator": "equals", "expression": "ARG"}]
}],
"rowLimit": 500,
"orderBy": [{"field": "clicks", "order": "descending"}]
}' | jq '.rows[] | {query: .keys[0], clicks: .clicks, impressions: .impressions, ctr: .ctr, position: .position}'
`
#### 10.2.9 Páginas con posición entre 4 y 10 (striking distance)
`bash
curl -X POST \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/searchAnalytics/query" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-05-13",
"endDate": "2026-06-10",
"dimensions": ["page","query"],
"dimensionFilterGroups": [{
"filters": [
{"dimension": "position", "operator": "greaterThanOrEqualTo", "expression": 4},
{"dimension": "position", "operator": "lessThanOrEqualTo", "expression": 10}
],
"groupType": "and"
}],
"rowLimit": 5000,
"orderBy": [{"field": "impressions", "order": "descending"}]
}' | jq '.rows[] | {page: .keys[0], query: .keys[1], position: .position, impressions: .impressions}'
`
#### 10.2.10 Sitemaps — listar sitemaps enviados
`bash
curl -s \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/sitemaps" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
| jq '.sitemap[] | {path: .path, lastSubmitted: .lastSubmitted, isPending: .isPending, warnings: .warnings, errors: .errors}'
`
#### 10.2.11 Enviar un sitemap nuevo
`bash
curl -X PUT \
"https://www.googleapis.com/webmasters/v3/sites/https%3A%2F%2Fwww.mdp.com.ar%2F/sitemaps/https%3A%2F%2Fwww.mdp.com.ar%2Fsitemap-noticias.xml" \
-H "Authorization: Bearer $(cat /tmp/gsc_token.txt)" \
-H "Content-Type: application/json"
`
#### 10.2.12 Script Bash completo — export semanal automatizado
Guardar como ~/.gsc/weekly_export.sh:
`bash
#!/bin/bash
set -euo pipefail
DOMAIN="${1:-mdp.com.ar}"
DAYS="${2:-28}"
SITE_URL="https%3A%2F%2F${DOMAIN}%2F"
TOKEN=$(python3 ~/.gsc/refresh_token.py)
AUTH="Authorization: Bearer ${TOKEN}"
CT="Content-Type: application/json"
END_DATE=$(date -u +%Y-%m-%d)
START_DATE=$(date -u -v-${DAYS}d +%Y-%m-%d)
OUTDIR="${HOME}/gsc-exports/$(date +%Y-%m-%d)"
mkdir -p "${OUTDIR}"
echo "📊 Exportando GSC para ${DOMAIN} (${START_DATE} → ${END_DATE})"
echo "📁 Directorio: ${OUTDIR}"
echo "→ Exportando queries..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"query\"],
\"rowLimit\": 500,
\"orderBy\": [{\"field\": \"clicks\", \"order\": \"descending\"}]
}" > "${OUTDIR}/queries.json"
echo "→ Exportando páginas..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"page\"],
\"rowLimit\": 500,
\"orderBy\": [{\"field\": \"clicks\", \"order\": \"descending\"}]
}" > "${OUTDIR}/pages.json"
echo "→ Exportando tendencia diaria..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"date\"],
\"rowLimit\": 100
}" > "${OUTDIR}/daily.json"
echo "→ Exportando por país..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"country\"],
\"rowLimit\": 50
}" > "${OUTDIR}/countries.json"
echo "→ Exportando por dispositivo..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"device\"],
\"rowLimit\": 10
}" > "${OUTDIR}/devices.json"
echo "→ Exportando striking distance..."
curl -s -X POST \
"https://www.googleapis.com/webmasters/v3/sites/${SITE_URL}/searchAnalytics/query" \
-H "${AUTH}" -H "${CT}" \
-d "{
\"startDate\": \"${START_DATE}\",
\"endDate\": \"${END_DATE}\",
\"dimensions\": [\"page\",\"query\"],
\"dimensionFilterGroups\": [{
\"filters\": [
{\"dimension\": \"position\", \"operator\": \"greaterThanOrEqualTo\", \"expression\": 4},
{\"dimension\": \"position\", \"operator\": \"lessThanOrEqualTo\", \"expression\": 10}
],
\"groupType\": \"and\"
}],
\"rowLimit\": 5000,
\"orderBy\": [{\"field\": \"impressions\", \"order\": \"descending\"}]
}" > "${OUTDIR}/striking_distance.json"
echo "→ Generando CSVs..."
for f in "${OUTDIR}"/*.json; do
base=$(basename "$f" .json)
jq -r '.rows[]? | [.keys[], .clicks, .impressions, .ctr, .position] | @csv' "$f" > "${OUTDIR}/${base}.csv" 2>/dev/null || true
done
echo "✅ Exportación completa: ${OUTDIR}"
ls -la "${OUTDIR}"
`
Hacer ejecutable y correr:
`bash
chmod +x ~/.gsc/weekly_export.sh
~/.gsc/weekly_export.sh mdp.com.ar 28
`