google-sheetsno-codedata-laketutorial

De Google Sheets a un Data Lake Consultable en 3 Comandos

Michael San Martim · 2026-04-26

Toda empresa tiene esa hoja de cálculo. El rastreador de presupuesto de marketing. El pronóstico de ventas. La hoja de ruta del producto con 47 pestañas. Vive en Google Sheets porque ahí es donde los equipos no técnicos trabajan.

Necesitas esos datos en tu data lake. No cómo una exportación CSV que recuerdas descargar los viernes. Como una tabla Parquet apropiada que puedas cruzar con tus datos de producción y consultar con SQL.

DataSpoc Pipe tiene un tap de Google Sheets integrado. Sin paquetes extra, sin danza de OAuth para hojas públicas, sin archivos de configuración de Singer. Tres comandos.

El Escenario

Tu equipo de marketing mantiene una hoja de Google Sheets con datos de gasto en campañas:

https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms/edit

Tiene dos hojas (pestañas):

  • campaigns — nombre de campaña, canal, presupuesto, gasto, fecha_inicio, fecha_fin
  • daily_metrics — fecha, campaña, impresiones, clics, conversiónes, costo

Quieres esto en tu data lake cómo Parquet, consultable con SQL, cruzable con tus datos de ingresos de Postgres.

Comando 1: Inicializar el Proyecto

Terminal window
dataspoc-pipe init marketing-lake --bucket s3://company-marketing

Salida:

Created project: marketing-lake/
dataspoc-pipe.yaml
pipelines/

Comando 2: Agregar el Pipeline de Google Sheets

Terminal window
dataspoc-pipe add sheets-marketing \
--source google_sheets \
--url "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms" \
--target s3://company-marketing

Esto genera la configuración del pipeline:

pipelines/sheets-marketing.yaml
pipeline: sheets-marketing
source:
type: google_sheets
url: "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
sheets:
- campaigns
- daily_metrics
target:
type: s3
bucket: s3://company-marketing
prefix: raw/google_sheets

Eso es todo. Sin claves de API necesarias para hojas públicas. Para hojas privadas, configura GOOGLE_SERVICE_ACCOUNT_JSON cómo variable de entorno.

Comando 3: Ejecutar

Terminal window
dataspoc-pipe run sheets-marketing

Salida:

[sheets-marketing] Starting extraction...
[sheets-marketing] Extracting sheet: campaigns (156 rows)
[sheets-marketing] Extracting sheet: daily_metrics (4,380 rows)
[sheets-marketing] Writing: s3://company-marketing/raw/google_sheets/campaigns/20260415_070000.parquet
[sheets-marketing] Writing: s3://company-marketing/raw/google_sheets/daily_metrics/20260415_070000.parquet
[sheets-marketing] Done. 2 tables, 4,536 rows, 3.2s

Tu data lake ahora tiene:

s3://company-marketing/
.dataspoc/
manifest.json
state/sheets-marketing/state.json
raw/google_sheets/
campaigns/
20260415_070000.parquet
daily_metrics/
20260415_070000.parquet

Consultar con DataSpoc Lens

Ahora conecta Lens y empieza a consultar:

Terminal window
dataspoc-lens add-bucket marketing s3://company-marketing
dataspoc-lens shell

Ahora estás en un shell SQL de DuckDB con tus datos de Sheets montados:

-- See available tables
SHOW TABLES;
┌─────────────────────────────────────┐
│ name │
├─────────────────────────────────────┤
│ raw__google_sheets__campaigns │
│ raw__google_sheets__daily_metrics │
└─────────────────────────────────────┘
-- Total spend by channel
SELECT
channel,
COUNT(*) as campaigns,
SUM(spend) as total_spend,
SUM(budget) as total_budget,
ROUND(SUM(spend) / SUM(budget) * 100, 1) as pct_used
FROM raw__google_sheets__campaigns
GROUP BY channel
ORDER BY total_spend DESC;
┌──────────┬───────────┬─────────────┬──────────────┬──────────┐
│ channel │ campaigns │ total_spend │ total_budget │ pct_used │
├──────────┼───────────┼─────────────┼──────────────┼──────────┤
│ google │ 45 │ 125,400 │ 150,000 │ 83.6 │
│ meta │ 38 │ 98,200 │ 120,000 │ 81.8 │
│ linkedin │ 22 │ 67,800 │ 80,000 │ 84.8 │
│ twitter │ 51 │ 34,500 │ 50,000 │ 69.0 │
└──────────┴───────────┴─────────────┴──────────────┴──────────┘
-- Cost per conversion by campaign (last 30 days)
SELECT
c.campaign_name,
c.channel,
SUM(d.cost) as total_cost,
SUM(d.conversions) as total_conversions,
ROUND(SUM(d.cost) / NULLIF(SUM(d.conversions), 0), 2) as cpa
FROM raw__google_sheets__daily_metrics d
JOIN raw__google_sheets__campaigns c ON d.campaign = c.campaign_name
WHERE d.date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY c.campaign_name, c.channel
HAVING SUM(d.conversions) > 0
ORDER BY cpa ASC
LIMIT 10;
┌──────────────────────┬──────────┬────────────┬──────────────────┬───────┐
│ campaign_name │ channel │ total_cost │ total_conversions│ cpa │
├──────────────────────┼──────────┼────────────┼──────────────────┼───────┤
│ spring_retargeting │ meta │ 2,340 │ 156 │ 15.00 │
│ brand_search │ google │ 4,200 │ 245 │ 17.14 │
│ lookalike_q2 │ meta │ 3,800 │ 198 │ 19.19 │
│ dev_tools_launch │ linkedin │ 5,600 │ 112 │ 50.00 │
└──────────────────────┴──────────┴────────────┴──────────────────┴───────┘

AI Ask: Consultas en Lenguaje Natural

Para exploración rápida, usa AI Ask:

Terminal window
dataspoc-lens ask "Which campaign had the best conversion rate last week?"

Salida:

SQL:
SELECT
c.campaign_name,
c.channel,
SUM(d.clicks) as clicks,
SUM(d.conversions) as conversions,
ROUND(SUM(d.conversions)::FLOAT / NULLIF(SUM(d.clicks), 0) * 100, 2) as conversion_rate
FROM raw__google_sheets__daily_metrics d
JOIN raw__google_sheets__campaigns c ON d.campaign = c.campaign_name
WHERE d.date >= CURRENT_DATE - INTERVAL '7 days'
GROUP BY c.campaign_name, c.channel
ORDER BY conversion_rate DESC
LIMIT 1
Result:
campaign_name: spring_retargeting
channel: meta
conversion_rate: 12.4%
Terminal window
dataspoc-lens ask "Compare Google vs Meta spend efficiency this month"
SQL:
SELECT
c.channel,
SUM(d.cost) as spend,
SUM(d.conversions) as conversions,
ROUND(SUM(d.cost) / NULLIF(SUM(d.conversions), 0), 2) as cost_per_conversion
FROM raw__google_sheets__daily_metrics d
JOIN raw__google_sheets__campaigns c ON d.campaign = c.campaign_name
WHERE d.date >= DATE_TRUNC('month', CURRENT_DATE)
AND c.channel IN ('google', 'meta')
GROUP BY c.channel
Result:
┌─────────┬────────┬─────────────┬─────────────────────┐
│ channel │ spend │ conversions │ cost_per_conversion │
├─────────┼────────┼─────────────┼─────────────────────┤
│ meta │ 12,400 │ 523 │ 23.71 │
│ google │ 18,900 │ 687 │ 27.51 │
└─────────┴────────┴─────────────┴─────────────────────┘

Mantenerlo Actualizado

Configura un cron para refrescar diariamente:

Terminal window
# Refresh sheets data every morning at 6am
0 6 * * * cd /opt/marketing-lake && dataspoc-pipe run sheets-marketing

O usa el horario integrado de Pipe:

pipelines/sheets-marketing.yaml
pipeline: sheets-marketing
schedule: "0 6 * * *"
source:
type: google_sheets
url: "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
sheets:
- campaigns
- daily_metrics
target:
type: s3
bucket: s3://company-marketing
prefix: raw/google_sheets

Hojas Privadas

Para hojas que no están compartidas públicamente, usa una Cuenta de Servicio de Google:

Terminal window
export GOOGLE_SERVICE_ACCOUNT_JSON=/path/to/service-account.json
dataspoc-pipe run sheets-marketing

Comparte la hoja con la dirección de correo de la cuenta de servicio, y funcióna exactamente igual.

Cruzar Datos de Sheets con Otras Fuentes

El verdadero poder es combinar datos de hojas de cálculo con tus datos de producción. Si también tienes un pipeline de Postgres:

-- Join marketing spend with actual revenue
SELECT
c.channel,
SUM(d.cost) as marketing_spend,
SUM(o.amount) as revenue,
ROUND(SUM(o.amount) / NULLIF(SUM(d.cost), 0), 2) as roas
FROM raw__google_sheets__daily_metrics d
JOIN raw__google_sheets__campaigns c ON d.campaign = c.campaign_name
JOIN raw__postgres__orders o ON o.utm_source = c.channel
AND o.created_at::DATE = d.date
WHERE d.date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY c.channel
ORDER BY roas DESC;

Por Qué Esto Funciona para Equipos Pequeños

  • Sin infraestructura — sin Airflow, sin Fivetran, sin dbt Cloud
  • Sin código — el equipo de negocio sigue editando su hoja de cálculo, tú obtienes Parquet
  • SQL sobre todo — una vez que es Parquet, es solo otra tabla
  • Listo para IA — AI Ask funcióna sobre datos de hojas de cálculo igual que sobre datos de producción
  • Gratis — DataSpoc Pipe es código abierto, la API de Google Sheets es gratis para uso razonable

Tres comandos. De hoja de cálculo pública a data lake consultable. Esa es la promesa de las herramientas de datos modernas.

Recomendados