---
name: set-up-offline-conversion-tracking
description: >-
  Closes the loop between the ad click and the CRM for lead-gen and SaaS accounts: creates
  import-type conversion actions for downstream stages (qualified lead, closed deal, paid
  conversion), gets GCLID and/or hashed-email capture wired into forms and the CRM, and runs the
  actual conversion uploads through VigilDog so Smart Bidding optimizes on business outcomes instead
  of raw form fills. VigilDog executes the action creation, the click/call conversion uploads, later
  value restatements, and the report-side verification; hidden-field capture and CRM plumbing are
  developer work. Use when lead quality is inconsistent or the real conversion happens days later in
  the CRM. Not for ecommerce purchases (tracked on-site via set-up-google-ads-conversion-tracking),
  not for web-tag attribution recovery (implement-enhanced-conversions), and post-import value
  corrections belong to configure-conversion-adjustments.
---
# Offline Conversion Tracking from CRM

## Purpose
For lead-gen and SaaS, the form submission is the top of the funnel, not the outcome. This skill
imports the downstream truth, qualified leads, proposals, closed deals, paid subscriptions, into
Google Ads with values, keyed to the original click (GCLID) or the lead's hashed email, so bidding
learns what a good lead looks like rather than what a cheap form fill looks like.

## When to run
- Lead quality varies and Smart Bidding on form fills produces volume without revenue.
- The business wants value-based bidding on deal values that only exist in the CRM.
- MQL/SQL/closed-won stages exist in a CRM and are not visible in Google Ads.
- An existing import pipeline broke or has never been verified.

## When NOT to run
- Ecommerce: purchases are tracked on-site, set-up-google-ads-conversion-tracking and
  set-up-cart-data-and-profit-tracking.
- The base web conversion does not exist yet, set-up-google-ads-conversion-tracking first; OCT
  supplements it.
- You only need to correct or retract already-imported conversions, configure-conversion-adjustments.
- You want better attribution of the web conversion itself, implement-enhanced-conversions.

## Prerequisites
- Working web conversion for the form fill / signup.
- A CRM that records lead source fields and stage transitions (HubSpot, Salesforce, etc.).
- Developer access for hidden form fields; CRM admin access for custom fields.
- A funnel map: which stages exist, roughly what each is worth (actual deal value for closed-won;
  for earlier stages, average deal value multiplied by that stage's historical close rate).
- EU/EEA traffic: consent state captured at form submission and stored with the lead.

## Procedure
1. Pick the identifier strategy with the user:
   - CRM can store the Google click id → click-id import.
   - CRM has email/phone but no click id → hashed-identifier matching (enhanced conversions for
     leads) on the web tag.
   - Both available → hybrid (recommended): click id wins when present, email matching fills
     cross-device and lost-parameter gaps.
   - Neither capturable → stop; there is nothing to join on until one exists.
2. Map the funnel: list stages, values, and which single stage bidding should optimize on. Start
   with the stage closest to revenue; resist importing every stage on day one.
3. Consult `gads_policy_guardrail` before the session's first Google Ads write. Then create one
   import-type conversion action per stage with `gads_create_conversion_action`: specific goal
   category (qualified lead / converted lead), per-conversion values enabled, one-per-click
   counting (a lead passes a stage once), click window matched to the sales cycle (30-90 days; 90
   is the ceiling). Preview each action, apply after explicit user approval. Classification: the
   revenue-nearest stage primary, intermediate stages secondary, and keep the existing web form
   action primary too for now.
4. HUMAN STEP (outside VigilDog): developer adds hidden fields to every lead form capturing the
   click id parameters (gclid and its app/web variants) from the URL, and the CRM stores them on
   the lead record along with consent state where required. Verify by submitting a test lead with
   a dummy click id and checking the CRM field.
5. HUMAN STEP (outside VigilDog), email path only: enable enhanced conversions in the Google Ads
   settings UI and wire the user-provided-data variable to the form-fill tag in GTM, so the email
   is captured hashed at lead time.
6. First import through VigilDog: take 5-10 real staged conversions from the CRM (user exports
   them), and upload with `gads_upload_click_conversions`, rows carry click id and/or email,
   exact conversion action name, conversion datetime with timezone, value, currency. Preview first
   (validate_only=true default) and show the user the parsed rows and any per-row errors; commit
   only after approval. Phone-call outcomes go through `gads_upload_call_conversions` the same
   way.
7. Read the upload result row by row: partial failures name the offending rows (name mismatch,
   date format, click outside window). Fix and re-run; never ignore partial success.
8. Verify in reports after 24-48 hours: `gads_run_gaql_query` segmented by conversion action, imported stages should appear with values matching the CRM sample.
9. Automate the cadence: agree a daily (ideal) or weekly export-and-upload rhythm. Each recurring
   VigilDog upload follows the same preview → approval → commit gate. HUMAN STEP alternatives
   (Zapier/Make triggers, scheduled sheet imports) are configured outside VigilDog if the user
   prefers.
10. As deals change after import, restate or retract with `gads_adjust_conversions` (see
    configure-conversion-adjustments for the full procedure).
11. After 30+ days of reliable imports, revisit classification: demote the web form fill to
    secondary via `gads_update_conversion_action` (preview → approval → commit) so bidding runs
    purely on CRM truth.

## Decision rules
- Exactly one offline stage primary at a time; multiple primary stages double-count into bidding.
- Keep the web form action primary alongside for the first 30 days; demote it only after imports
  have proven reliable, flipping early starves bidding during the transition.
- Click window: sales cycle length, capped at 90 days. Cycles longer than 90 days → make an
  earlier in-window stage (MQL/SQL) the primary and import closed-won as secondary reporting.
- Stage values without actuals: average deal value × stage-to-close rate (e.g., 10,000 average ×
  25% SQL close rate → 2,500 SQL value).
- Upload frequency: daily beats weekly, fresher signal, faster Smart Bidding feedback; real-time
  on stage change is best of all.
- Conversion name matching is exact-string; always copy from `gads_list_conversion_actions`
  output, never retype.
- Low email match rates → check for whitespace/casing issues in the email field and prefer the
  hybrid identifier strategy.
- Volume reality check before promising Smart Bidding gains: a primary stage that produces only
  a handful of conversions a month cannot drive target-based bidding well, pick the deepest
  stage that still clears roughly 30 conversions per month for the optimizing campaigns.

## Common failure modes
- Hidden-field script silently broken so click ids never reach the CRM, test with a dummy
  parameter before relying on months of lead data.
- Conversion datetime formatted wrongly or missing timezone, failing whole uploads.
- Importing conversions older than the click window and concluding "OCT doesn't work".
- Making every funnel stage primary "for visibility" and wrecking the bidding signal.
- Building the pipeline but never reconciling: schedule a weekly CRM-vs-Google-Ads count
  comparison via `gads_run_gaql_query` in the weekly review.

## Related skills
- Run before: set-up-google-ads-conversion-tracking (required), configure-google-consent-mode
  (EU/EEA).
- Run after: configure-conversion-adjustments (restatements), set-up-custom-variables (extra
  dimensions on the same uploads), set-up-value-based-bidding / set-up-conversion-based-bidding
  once import volume supports it.
