Si llevas RevOps en una empresa B2B, HubSpot tiene los datos. Lo que no tiene es una respuesta limpia a las dos preguntas que realmente mueven decisiones de pipeline: dónde están los deals atascados demasiado tiempo en cada stage, y cómo de bien están convirtiendo los leads entre lifecycle stages. Los informes nativos de HubSpot te dicen cuántos deals tienes y qué revenue cerró. No te muestran los cuellos de botella ni las fugas del funnel.
Esta guía es para conseguir esa visibilidad en Google Sheets, donde puedes joinear datos de HubSpot con paid media, segmentar por fuente y owner, compartirlo sin dar acceso CRM a todo el mundo, y — lo más importante — construir dos dashboards que el resto de tutoriales de conectores se saltan: un tracker de velocidad de transición entre stages y un waterfall de conversión de lifecycle.
Tres métodos para poner los datos a fluir (manual, Apps Script, conector programado), los gotchas específicos de HubSpot en cada capa, y el setup field-a-field de los dos dashboards. Los métodos son medios. Los dashboards son el objetivo. Cubrimos el mismo workflow para plataformas de paid en nuestras guías de LinkedIn Ads a Google Sheets y Meta Ads a Google Sheets; este post extiende a reporting CRM específico. Para la capa de integridad de datos analytics (sampling, thresholding, cardinalidad), mira nuestra guía de GA4 a Google Sheets; para la capa de confianza SEO (queries anonimizadas, muro de 16 meses), la de Search Console a Google Sheets.
Dónde viven los datos de lifecycle y velocity en HubSpot
Antes de elegir un método, necesitas saber dónde guarda HubSpot los timestamps que vas a consultar. Las fechas de lifecycle stage están repartidas en varias properties de "date entered/exited" — un par por stage, en cada registro de Contact y Deal. El stage actual es un field; el historial de transiciones está en esas date properties.
Para Contacts (usadas en el waterfall de lifecycle):
hs_lifecyclestage_lead_datehs_lifecyclestage_marketingqualifiedlead_datehs_lifecyclestage_salesqualifiedlead_datehs_lifecyclestage_opportunity_datehs_lifecyclestage_customer_datehs_lifecyclestage_evangelist_date,hs_lifecyclestage_other_datelifecyclestage— solo valor actual, no el historial
Para Deals (usadas en el dashboard de velocity por stage):
hs_v2_date_entered_<stagename>yhs_v2_date_exited_<stagename>— un par por stage del pipelinedealstage— solo stage actualcreatedate,closedate— para el age total del deal
La velocity es el gap entre dos timestamps. "Días de MQL a SQL" es hs_lifecyclestage_salesqualifiedlead_date menos hs_lifecyclestage_marketingqualifiedlead_date. "Días atascado en Presentation Scheduled" es TODAY() menos hs_v2_date_entered_presentationscheduled, solo cuando hs_v2_date_exited_presentationscheduled está vacío.
Si no extraes esas columnas de fecha, no puedes construir informes de velocity. La vista de lista por defecto de HubSpot no las muestra; tienes que personalizar la vista (UI), seleccionarlas por nombre (API), o elegirlas en el field picker (conector). La sección de cada método explica cómo.
Método 1: Export manual a CSV desde la UI de HubSpot
Para auditorías puntuales y snapshots ejecutivos. Rápido, gratis, e inútil para tracking de velocity recurrente, porque el lunes que viene los datos ya están desactualizados.
Setup: en HubSpot, abre la vista de lista (Contacts o Deals), aplica filtros, haz clic en Actions → Export. Críticamente — y aquí es donde la mayoría de exports salen mal para RevOps — selecciona explícitamente las properties de lifecycle date en el property picker. Si solo marcas las columnas por defecto, obtienes el stage actual sin fechas de transición. El export te manda un email con el link de descarga del CSV; impórtalo a Sheets vía Archivo → Importar.
Gotchas específicos de HubSpot en esta capa:
- Los caps de filas por export escalan con el Hub tier. Marketing Hub Starter está capado a 10.000 filas por export; Professional a 50.000; Enterprise más alto pero también limitado. Para portales con cientos de miles de contacts, vas a tener que exportar en segmentos por lifecycle stage o rango de fechas, y luego concatenar en Sheets.
- Las fechas de HubSpot se exportan como strings ISO 8601, no como fechas nativas de Sheets. Puede que necesites un wrapper
DATEVALUEsi quieres hacer aritmética con fechas. - Las custom properties se exportan por su internal name, no por la etiqueta UI. Si tu equipo llama a una property "First meeting date" pero el internal name es
prop_first_meeting_date_c, el header de la columna en el CSV será el internal name.
Cuándo encaja este método: snapshot trimestral para board, auditoría antes de una limpieza CRM, export puntual para un deck anual.
Cuándo no: cualquier dashboard donde los datos tengan que refrescarse a diario.
Método 2: Apps Script con la HubSpot CRM API
El camino gratis para cuando un equipo de RevOps interno quiere refresh diario de velocity sin suscripción a un conector. El setup son 30–60 minutos la primera vez; 10–15 minutos por cada object type adicional. El mantenimiento es tuyo.
Paso 1 — Crea una Private App en HubSpot. Settings → Integrations → Private Apps → Create a private app. Scopes mínimos para el dashboard de velocity: crm.objects.contacts.read, crm.objects.deals.read, crm.objects.companies.read. Añade crm.lists.read si quieres filtrar por listas guardadas de HubSpot. Crea la app y HubSpot genera un access token de larga duración. Guárdalo seguro.
Paso 2 — En tu Sheet, abre Extensiones → Apps Script y pega el script de abajo. Extrae deals junto con las fechas de transición de stage que alimentan el dashboard de velocity.
function exportHubSpotDealsForVelocity() {
const HUBSPOT_TOKEN = 'YOUR_PRIVATE_APP_TOKEN';
// Extrae datos de deal + timestamps de transición de stage. Ajusta los nombres de stage a tu pipeline.
const properties = [
'dealname','amount','pipeline','dealstage','createdate','closedate','hubspot_owner_id',
'hs_v2_date_entered_qualifiedtobuy','hs_v2_date_exited_qualifiedtobuy',
'hs_v2_date_entered_presentationscheduled','hs_v2_date_exited_presentationscheduled',
'hs_v2_date_entered_contractsent','hs_v2_date_exited_contractsent',
'hs_v2_date_entered_closedwon','hs_v2_date_entered_closedlost'
].join(',');
const baseUrl = 'https://api.hubapi.com/crm/v3/objects/deals';
const options = {
method: 'GET',
headers: { 'Authorization': 'Bearer ' + HUBSPOT_TOKEN, 'Content-Type': 'application/json' },
muteHttpExceptions: true
};
const sheet = SpreadsheetApp.getActiveSheet();
sheet.clear();
sheet.appendRow(['Deal ID','Deal Name','Amount','Pipeline','Current Stage','Created','Closed',
'Entered Qualified','Exited Qualified',
'Entered Presentation','Exited Presentation',
'Entered Contract Sent','Closed Won']);
let after = null;
do {
const url = baseUrl + '?limit=100&properties=' + properties + (after ? '&after=' + after : '');
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
(data.results || []).forEach(row => {
const p = row.properties || {};
sheet.appendRow([
row.id, p.dealname, p.amount, p.pipeline, p.dealstage,
p.createdate, p.closedate,
p.hs_v2_date_entered_qualifiedtobuy, p.hs_v2_date_exited_qualifiedtobuy,
p.hs_v2_date_entered_presentationscheduled, p.hs_v2_date_exited_presentationscheduled,
p.hs_v2_date_entered_contractsent, p.hs_v2_date_entered_closedwon
]);
});
after = data.paging && data.paging.next ? data.paging.next.after : null;
} while (after);
}Paso 3 — Prográmalo. Apps Script → Triggers (icono reloj) → Add Trigger → corre exportHubSpotDealsForVelocity diariamente a las 6 AM. Tu sheet de velocity se refresca antes del stand-up del equipo.
Gotchas específicos de HubSpot en la capa API:
- Paginación basada en cursor, no en offset. HubSpot devuelve
paging.next.after; pásalo de vuelta comoafter=en la siguiente petición. No intenteslimit=10000de una — HubSpot capa a 100 por página en la API v3. - Las rate limits escalan con el Hub tier. Marketing Hub Free: 100 req/10s y 250.000/día. Professional: 150/10s y 500.000/día. Enterprise: 200/10s. Si consultas 50K+ deals al día, vigila la cuota diaria.
- Las custom properties se consultan por internal name, no por etiqueta. Encuentra los internal names en Settings → Properties → click en la property → campo "Internal name".
- Los nombres de stage del pipeline son específicos del pipeline.
qualifiedtobuyes default del pipeline de ventas estándar. Pipelines custom tienen internal names custom — visibles en Settings → Pipelines → click en el pipeline → cada stage muestra su internal name. Actualiza la lista depropertiesen el script. - Límite de ejecución de Apps Script. Workspace gratis: 6 minutos; Workspace de pago: 30 minutos. Extraer 50K+ deals con muchas properties puede chocarlo. Soluciones: extraer deals en segmentos por rangos de
createdate, o pasar al Método 3.
La referencia oficial de HubSpot CRM API v3 documenta cada endpoint y sintaxis de filtro por property.
Sáltate el mantenimiento de Apps Script
Dataslayer conecta HubSpot con Google Sheets, Looker Studio (ahora Data Studio), BigQuery y Power BI de forma programada. Soporte multi-portal, mappings pre-construidos para contacts, deals, companies, tickets, email campaigns y line items.
Prueba Dataslayer GratisMétodo 3: Conector programado (no-code)
El camino para equipos de RevOps con múltiples portales (agencias), sin apetito para mantenimiento de código, o que necesitan acceso a dimensiones derivadas que la API bare no expone limpiamente.
Dataslayer conecta HubSpot con Sheets vía OAuth en menos de 10 minutos. Desde Google Sheets: Extensiones → Complementos → Obtener complementos → instala Dataslayer. Luego Extensiones → Dataslayer → Abrir Sidebar, elige HubSpot, autoriza vía el flujo OAuth de HubSpot, elige el portal (o portales), elige objetos, elige fields, configura el rango de fechas, haz clic en Run.
Por qué un conector específicamente gana para trabajo de HubSpot RevOps:
- Multi-portal nativo. Agencias gestionando 5–20 portales de cliente los consultan en el mismo workbook con una columna de portal para diferenciar. Dataslayer agrupa las llamadas API entre portales respetando las rate limits por portal.
- Superficie de custom properties. El field picker de Dataslayer expone el schema completo de HubSpot (el schema de Dataslayer cubre 934 dimensiones y 249 métricas) categorizado por fechas de lifecycle, atribución de marketing, geo, content, y pipeline. Encontrar
hs_lifecyclestage_marketingqualifiedlead_dateno requiere acordarse del internal name. - Fields derivados pre-computados. Days-since-created, days-in-current-stage, days-since-last-engagement — calculados por el conector para no tener que escribir fórmulas en Sheets para lo básico.
- Conciencia multi-pipeline. Si tienes pipelines separados para new business y renovaciones, Dataslayer expone los internal names de stage por pipeline; no tienes que buscar uno por uno.
Costes: Gratis para 1 conector y 1 usuario. Starter $35/mes anual cubre 3 conectores y 1 destino. El tier Pro hace falta para >5 portales o >100 cuentas.
El gotcha de HubSpot que NINGÚN método arregla: la feature Operations Hub Data Sync NO es un conector a Google Sheets. Data Sync mantiene HubSpot en sync con otros CRMs (Salesforce, Pipedrive). Para HubSpot → Sheets, los tres métodos de este post son los caminos prácticos. No pierdas tiempo buscando un puente Data Sync → Sheets; no existe.
Los 2 dashboards RevOps que merecen la pena construir
Una vez los datos fluyen a Sheets (cualquiera de los 3 métodos), aquí están los dos informes que cambian cómo opera RevOps. Ninguno es algo que la UI nativa de HubSpot muestre bien, y ambos requieren las date properties de lifecycle.
Dashboard 1: Tracker de velocidad de transición entre stages
La pregunta: ¿cuánto tiempo están sentados los deals en cada stage del pipeline, y dónde está el cuello de botella?
Columnas a extraer de HubSpot:
- Deal ID, Deal Name, Amount, Deal Owner, Current Stage, Created Date, Close Date
hs_v2_date_entered_qualifiedtobuy,hs_v2_date_exited_qualifiedtobuyhs_v2_date_entered_presentationscheduled,hs_v2_date_exited_presentationscheduledhs_v2_date_entered_contractsent,hs_v2_date_exited_contractsenths_v2_date_entered_closedwon
Cálculos en Sheets:
- Días en stage actual:
=SI(<exited_current_stage> = "", HOY() - <entered_current_stage>, "") - Días en Qualified:
=<exited_qualified> - <entered_qualified> - Mediana de días en cada stage por trimestre usando
=CUARTIL()o=MEDIANA()filtrado por trimestre
Layout de pivot:
- Filas: stage del pipeline
- Columnas: trimestre (o mes)
- Valores: PROMEDIO(días en stage)
- Formato condicional: resalta celdas donde la velocity bajó >20% vs trimestre anterior
Qué saca a la luz que la UI de HubSpot no:
- Deals atascados en "Presentation Scheduled" más de 45 días — el equipo de ventas no está haciendo seguimiento
- La mediana "Qualified → Contract Sent" se duplicó este trimestre — cambiaron los criterios de cualificación y nadie se enteró
- Velocity por Deal Owner revela quién es lento vs rápido, y dónde hace falta coaching
Dashboard 2: Waterfall de conversión de lifecycle
La pregunta: de los contacts que se convirtieron en MQL el trimestre pasado, ¿cuántos pasaron a SQL, luego a Opportunity, y luego a Customer — y a qué ratio por fuente de adquisición?
Columnas a extraer de HubSpot:
- Contact ID, Email, Original Source, Original Source Drill-down 1, Latest Converting Campaign
hs_lifecyclestage_lead_datehs_lifecyclestage_marketingqualifiedlead_datehs_lifecyclestage_salesqualifiedlead_datehs_lifecyclestage_opportunity_datehs_lifecyclestage_customer_date
Cálculos en Sheets:
- Conversion rate MQL → SQL (trimestral): ratio de CONTAR.SI.CONJUNTO donde la fecha SQL está en el trimestre vs CONTAR.SI.CONJUNTO donde la fecha MQL está en el trimestre
- Media de días MQL → SQL: promedio de
SQL_date - MQL_datepara contacts donde ambas están pobladas - Retención por cohorte: agrupa contacts por trimestre en que entraron a MQL, luego trackea qué porcentaje llegaron a SQL, Opportunity, Customer en trimestres posteriores
Layout de pivot:
- Filas: original source (Organic, Paid, Direct, Referral, Email)
- Columnas: transiciones de lifecycle (MQL→SQL, SQL→Opp, Opp→Customer)
- Valores: porcentaje de conversion rate
Qué responde este dashboard que el QBR no podría:
- Qué canales de adquisición producen los movers más rápidos (no solo los más leads)
- Dónde el funnel pierde gente de verdad — ¿es el handoff marketing-a-sales (MQL→SQL) o la ejecución de sales (Opp→Customer)?
- Si los cambios en los criterios de MQL scoring el trimestre pasado realmente mejoraron la conversion downstream o solo cambiaron el volumen
Para mejores prácticas de layout de dashboards una vez que estos informes estén corriendo, mira nuestro Playbook de KPIs de Marketing Dashboard. Para atribución cross-source (joineando datos de HubSpot con paid media para validar qué campañas producen los deals que cierran), mira Por Qué la Atribución de Marketing Está Rota en 2026.
Comparando los tres métodos
| Aspecto | CSV manual | Apps Script | Conector programado |
|---|---|---|---|
| Tiempo de setup | 5 min | 30-60 min | Menos de 10 min |
| Coste | Gratis | Gratis | Desde $35/mes |
| Properties de lifecycle date | Hay que elegirlas manualmente | Hay que pedir por internal name | En field picker, categorizadas |
| Refresh programado | No | Sí (Apps Script triggers) | Sí (built-in) |
| Multi-portal | Un export por portal | Un script por portal | Nativo, una query |
| Custom properties | Por internal name | Por internal name | Por etiqueta, auto-mapeadas |
| Mantenimiento de código | Ninguno | Owner | Proveedor |
La decisión normalmente baja a número de portales y al apetito del equipo por código. Un portal y tienes un developer en el equipo: Apps Script. Múltiples portales o RevOps es tu trabajo full-time: conector programado. Solo necesitas un export para un deck ejecutivo este viernes: CSV manual.
Quirks de HubSpot que vale la pena saber
Cinco comportamientos específicos de HubSpot que afectan a cada método y a cada dashboard que construyas:
- Internal names de custom properties ≠ etiquetas. Siempre verifica Settings → Properties → "Internal name" antes de escribir llamadas a la API o filtros.
- Los nombres de stage de pipeline son específicos del pipeline.
qualifiedtobuyes el stage "Qualified to Buy" del pipeline de ventas default. Pipelines custom tienen internal names diferentes por stage. Settings → Pipelines → cada stage muestra su internal name. - Marketing Hub Free capa la API a 100 req/10s y 250K/día. Planifica queries multi-portal para mantenerte por debajo.
- Operations Hub Data Sync no es un conector a Google Sheets. Es HubSpot ↔ otros CRMs. No pierdas tiempo buscando un puente a Sheets ahí.
- Los informes de multi-touch attribution se computan server-side. La API expone los inputs (campañas, fuentes, touchpoints), pero para el multi-touch attribution calculado final, el informe in-app de HubSpot sigue siendo la fuente de verdad. Tu Sheet puede replicar first-touch y last-touch, no multi-touch.
Errores comunes y cómo leerlos
Algunos errores aparecen lo bastante como para que reconocerlos ahorre tiempo.
401 unauthorized: el access token es inválido o ha sido revocado. Regenera el token de la private app en HubSpot Settings → Integrations → Private Apps y actualiza tu script o configuración de conector.
403 forbidden con error de scope: la private app no tiene el scope necesario para leer el objeto solicitado. Edita la private app, añade el CRM scope que falta, guarda y reintenta. La documentación de HubSpot Private Apps lista cada scope y qué concede.
429 too many requests: chocaste con la rate limit de la HubSpot API. Espera y reintenta; o escalona tu agenda de refresh entre varios momentos del día si corres consultas de varios portales.
Array results vacío sin error: el filtro que aplicaste excluye todos los registros. Causa típica: filtrar por un property name que no existe o por un date field con formato inesperado (las fechas de HubSpot son milisegundos desde epoch; entrecomillarlas como string no matchea).
FAQ
¿Cómo encuentro el internal name de una custom property de HubSpot?
Settings → Properties → elige el objeto (Contact, Deal, etc.) → haz clic en el nombre de la property → el campo "Internal name" muestra el valor a usar en tu llamada API o conector de Sheets. Los internal names suelen tener un sufijo _c y pueden usar guiones bajos; las etiquetas son legibles para humanos.
¿Necesito Marketing Hub Professional o superior para usar la CRM API?
No. La HubSpot CRM API está disponible en cada tier incluyendo Marketing Hub Free. La restricción son las rate limits: Free da 100 requests cada 10 segundos y 250.000 al día; Professional da 150/10s y 500K/día; Enterprise da 200/10s. Para un setup típico de reporting en Sheets extrayendo deals y contacts diariamente, el tier Free es suficiente.
¿Por qué las fechas de lifecycle stage están en blanco para algunos contacts?
HubSpot solo registra la fecha cuando un contact realmente pasa por ese stage. Un contact creado directamente como MQL se salta hs_lifecyclestage_lead_date (está en blanco), pero tiene hs_lifecyclestage_marketingqualifiedlead_date poblado. Las fórmulas de tu dashboard necesitan manejar blancos (usa patrones SI(fecha<>"", ..., "")).
¿HubSpot Operations Hub Data Sync es lo mismo que un conector a Google Sheets?
No. Operations Hub Data Sync mantiene HubSpot en sync con otros CRMs (Salesforce, Pipedrive, Microsoft Dynamics), no con Google Sheets. Para HubSpot → Sheets, los tres métodos de este post son los caminos prácticos; no hay feature nativa de HubSpot para esa dirección.
¿Debería usar Private App u OAuth para mi integración de Apps Script?
Private apps para uso interno (tu propio portal, tu propio equipo, tu propio Sheet). OAuth solo si estás construyendo software que otras cuentas de HubSpot van a instalar. Para "quiero extraer los datos de mi propio portal a mi propio Sheet", siempre usa una private app — es más simple y evita el proceso de OAuth app review.
¿Puedo mandar datos de Sheets de vuelta a HubSpot?
Sí, pero requiere write scopes en la private app y peticiones POST/PATCH en lugar de GET. La CRM API soporta bulk updates de contacts y deals. Este post cubre la dirección de lectura (HubSpot → Sheets) que es lo que el reporting de RevOps necesita; los patrones de write-back (Sheets → HubSpot para bulk update de properties) son un workflow separado.
¿Cómo afecta el rebrand de Looker Studio a Data Studio al reporting de HubSpot en Sheets?
No lo afecta. El rebrand fue un cambio de nombre, no de producto. Las conexiones existentes de HubSpot a lo que ahora se llama Data Studio siguen funcionando. Cubrimos los detalles del rebrand en nuestro post sobre el rebrand de Looker Studio a Data Studio.
Conclusión
Los tres métodos para extraer datos de HubSpot a Google Sheets existen en un espectro: CSV manual para auditorías puntuales, Apps Script para automatización gratis con mantenimiento de código, conector programado para reporting RevOps multi-portal sin manos. El método correcto depende del número de portales, el apetito del equipo por código, y la frecuencia con que los datos tengan que refrescarse.
Pero los métodos son medios, no el fin. El deliverable son los dos dashboards: un tracker de velocidad de transición de stage que muestra dónde está atascado el pipeline, y un waterfall de conversión de lifecycle que cuantifica el funnel y el camino fuente-a-revenue. Ambos requieren extraer las date properties de lifecycle — y la mayoría de equipos se saltan esas columnas en su primer export, luego se preguntan por qué su workflow HubSpot → Sheets no cambia nada en cómo RevOps toma decisiones.
Extrae las columnas de fecha. Construye los dashboards. El conector es un fin de semana de setup; el insight de velocity es algo a lo que vas a recurrir cada lunes durante el próximo año. Empieza una prueba gratis de Dataslayer si quieres saltarte el mantenimiento de la API y llegar a los dashboards más rápido.


.avif)




