Digital Marketing Tools and Technologies
Data Analysis and Reporting in Marketing

Stripe to Looker Studio in 2026: Trial Conversion Funnel and Dunning Recovery Dashboards for SaaS Marketers

Adela
May 20, 2026
Stripe to Looker Studio: Trial Conversion & Dunning (2026)

If you run paid acquisition for a SaaS, freemium, or trial-based business in 2026, the Stripe Dashboard tells you what revenue you made. What it does not tell you is which signups from your $50,000 of Meta Ads spend last month actually converted from trial to paid, how many got stuck in dunning at month two, and which acquisition channels recover failed payments versus which ones churn silently. Most SaaS marketers operate on signup counts because the trial-to-paid funnel and the failed payment funnel are invisible inside the default Stripe reporting.

This guide covers three methods to pull Stripe data into Looker Studio in 2026, the Stripe-specific gotchas at each layer, and the two SaaS marketing dashboards that change how acquisition is measured: the trial conversion funnel by acquisition channel and dunning recovery by acquisition channel. Neither is a default Stripe Dashboard view, both require joining Stripe data to your marketing source attribution, and both decide whether your paid acquisition is genuinely profitable or just looks that way for thirty days.

For the related layer of marketing reporting around this, see our marketing dashboard KPIs playbook, our existing Stripe to Google Sheets guide for the spreadsheet path, and our LinkedIn Ads to Google Sheets guide for the B2B paid acquisition source most SaaS companies care about. This post focuses on Looker Studio specifically and on the subscription-funnel angle. A quick note on naming: Google renamed Looker Studio back to Data Studio in early 2026, but in search behavior and in everyday use most marketers still call it Looker Studio, so that is the name we use throughout. The product, the connector ecosystem, and the pricing are unchanged.

Where the subscription funnel lives in Stripe

Before picking a method, you need to know what Stripe exposes and where the relevant fields hide. The trial-to-paid funnel and the dunning funnel both span several Stripe objects.

  • Customer. The top-level record. Carries the created date (your signup-equivalent timestamp), metadata (where most teams store the acquisition channel or UTM source), and links to subscriptions, charges, invoices, and payment methods.
  • Subscription. The subscription record. Carries status (trialing, active, past_due, canceled, unpaid, incomplete), trial_start and trial_end dates, start_date, canceled_at, and the structured cancellation_details object with reason and feedback fields populated by your churn surveys.
  • Invoice. The billing artifact. Carries attempt_count (how many times Stripe retried a failed payment), next_payment_attempt, and status (draft, open, paid, void, uncollectible). The dunning funnel lives inside invoice attempt counts and status transitions.
  • PaymentIntent. The payment attempt. Carries status (succeeded, requires_payment_method, canceled) and last_payment_error.code, which tells you whether the failure was a card declined, insufficient funds, expired card, or fraud block. Recovery rate varies dramatically by failure reason.
  • Charge. The successful payment. Where the actual revenue is recorded with currency, refund history, and dispute information.

For the marketing acquisition story, the critical piece is the metadata field on Customer (or Subscription) where your signup form stamps the acquisition channel. If your signup form does not write to metadata, you are flying blind. Stripe will not infer marketing channel from anywhere else.

Method 1: Manual CSV export from the Stripe Dashboard

For one-off audits, monthly board snapshots, or before you have a real reporting setup. Fast, free, brittle the moment you need any segmentation.

Setup: in Stripe Dashboard, navigate to Customers, Subscriptions, or Invoices. Click Export. Choose CSV. Choose date range. Download. Open in Sheets. Manually join across exports if you need a complete funnel view.

Stripe-specific gotchas at this layer:

  • Each export is a single object type. A trial-to-paid funnel needs customers, subscriptions, AND invoices joined. That is three exports per snapshot, then VLOOKUP gymnastics in Sheets to stitch them together.
  • Metadata is not included in default exports. Your custom channel field stored in metadata typically requires either the Sigma SQL layer or the API. The default Stripe CSV export gives you canonical fields only.
  • No incremental refresh. Every export is a fresh download from start. Building a weekly cadence means accumulating snapshots forward yourself in Sheets.
  • Cancellation reasons require the survey to be live. The cancellation_details.reason field only populates when you have configured the Stripe Billing Portal cancellation survey. Most teams configure it once, then forget; check that survey responses are being captured before you build a churn-by-reason dashboard.

When this method fits: board snapshot, quarterly review, audit before you invest in real tooling.

When it does not: any dashboard that refreshes more than monthly, anything joining Stripe to your paid media spend, anything segmenting by acquisition channel.

Method 2: Apps Script with the Stripe API

The DIY path for a SaaS marketing or RevOps team comfortable with a bit of code. Setup is 45-90 minutes the first time, then 20-30 minutes per additional report. The result lands in Sheets, which then connects to Looker Studio as the data source.

Step 1. Generate a Stripe restricted API key. In Stripe Dashboard: Developers, then API keys, then Create restricted key. Scope it to read access on Customers, Subscriptions, Invoices, Charges, and PaymentIntents only. Never use a full secret key for read workflows; restricted keys are scoped and revocable.

Step 2. In your Google Sheet, open Extensions, then Apps Script and paste a script along these lines:

function exportStripeSubscriptionsWithChannel() {
  const STRIPE_KEY = 'rk_live_YOUR_RESTRICTED_KEY';
  const baseUrl = 'https://api.stripe.com/v1/subscriptions';
  const headers = {
    'Authorization': 'Bearer ' + STRIPE_KEY,
    'Stripe-Version': '2024-09-30.acacia'
  };

  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.clear();
  sheet.appendRow(['Subscription ID', 'Customer ID', 'Status', 'Trial Start', 'Trial End', 'Start Date', 'Canceled At', 'Cancellation Reason', 'Acquisition Channel']);

  let url = baseUrl + '?limit=100&expand[]=data.customer';
  while (url) {
    const response = UrlFetchApp.fetch(url, { headers: headers, muteHttpExceptions: true });
    const data = JSON.parse(response.getContentText());
    (data.data || []).forEach(sub => {
      const channel = (sub.customer && sub.customer.metadata) ? sub.customer.metadata.acquisition_channel : '';
      const reason = (sub.cancellation_details) ? sub.cancellation_details.reason : '';
      sheet.appendRow([sub.id, sub.customer.id, sub.status, sub.trial_start, sub.trial_end, sub.start_date, sub.canceled_at, reason, channel]);
    });
    url = data.has_more ? baseUrl + '?limit=100&starting_after=' + data.data[data.data.length - 1].id + '&expand[]=data.customer' : null;
  }
}

The Stripe API reference documents every endpoint, expand parameter, and pagination pattern. The API versioning docs explain how the Stripe-Version header works. For dunning behavior specifics, see the Stripe Smart Retries documentation.

Step 3. Connect the Sheet to Looker Studio. In Looker Studio, Create, then Data source, then Google Sheets connector, point at your Stripe sheet, click Connect. Refresh schedule is configurable from the Looker Studio side; the Apps Script trigger handles the underlying refresh from Stripe.

Step 4. Schedule the Apps Script. Apps Script, Triggers, Add Trigger, run your function daily before the team check-in.

Stripe-specific gotchas at the API layer:

  • API versioning matters more than you think. The Stripe-Version header pins which API version you call. Pin a version (a 2025 or early 2026 dated revision is the current standard) and stick to it. When Stripe deprecates one, they give you a long migration window, but they do not run forever.
  • Rate limits exist but are generous. Stripe documents roughly 100 read operations per second in live mode and 25 per second in test mode. You will not hit them for typical reporting workloads. Build retry-on-429 anyway for safety; rare bursts happen.
  • Pagination is cursor-based with starting_after. Stripe does not page by page number; you pass the last object ID from the previous page. The has_more field signals the end. Skip pagination logic and you only get the first 100 records.
  • Use expand to inline related objects. By default, the customer field on a subscription is just a customer ID. To get the metadata, pass expand[]=data.customer. Each expand level adds latency; do not expand more than two levels deep.
  • Restricted keys are scoped and revocable. If your script gets compromised, you revoke the restricted key in the Dashboard and nothing else breaks. Never use the unrestricted secret key (sk_live_ with full access) in spreadsheets, repositories, or unmanaged endpoints.
  • Test mode versus live mode are separate. The rk_test_ prefix queries test data; rk_live_ queries production. Confusing them is the most common pre-launch mistake. The Stripe Dashboard top-right has a toggle; the API key prefix should match the mode you intend.
  • Apps Script execution limit. Workspace Free: 6 minutes per execution. Workspace paid: 30 minutes. Pulling a year of subscriptions plus customer expansion plus invoices can blow past 6 minutes. Solution: process by month chunks, or move the workflow to Cloud Functions if you need longer runs.

Skip the Apps Script maintenance

Dataslayer connects Stripe directly to Looker Studio, Google Sheets, BigQuery, and Power BI on a schedule. Subscription status, cancellation reasons, subscription metadata, trial dates, and invoice status transitions exposed as native fields. Bring your acquisition channel alongside the funnel data and your dashboard refreshes itself.

Try Dataslayer Free

Method 3: Scheduled no-code connector

The path for SaaS marketing teams that want Stripe data in Looker Studio on a schedule with no code, no API maintenance, and the acquisition channel field already aligned. Setup under 10 minutes.

Dataslayer connects Stripe to Looker Studio via the Stripe restricted API key flow. The connector queries the same Stripe API the manual script does, but exposes subscription status, cancellation reasons, subscription metadata, trial dates, and invoice status as native queryable dimensions in your Looker Studio data source. You point Looker Studio at the Dataslayer connector, pick the fields, and the dashboard refreshes on the schedule you set.

Why a connector matters specifically for SaaS marketing reporting:

  • Subscription funnel states as native fields. Status, trial_start, trial_end, canceled_at, and cancellation_reason ship as dimensions you can pivot directly. No JSON parsing, no expand path syntax.
  • Subscription metadata exposed as fields. If you stamp the acquisition channel into subscription.metadata at signup (in addition to customer.metadata), the connector exposes it as a native dimension you can pivot directly. That is the field that lets you segment trial conversion by channel without JSON extraction work; native customer-level metadata extraction is on the connector roadmap.
  • Joined to paid media in one workbook. Once Stripe and Meta Ads or LinkedIn Ads data both feed Looker Studio via the same connector layer, blended CAC by channel is a calculated field away.
  • Past invoice retrieval is opt-in. The connector exposes a setting to pull historical invoices (with the API cost that implies). For ongoing dashboards you do not need this; for backfilling a year of dunning data once, you turn it on.

Costs: a free tier covers a single connector and user; paid tiers scale up to multiple Stripe accounts in one workspace. Current pricing here.

The Stripe gotcha that NO method fixes: if your signup form does not write the acquisition channel to metadata at customer creation, no dashboard can recover the data. Fix the signup form first. Stamp utm_source, utm_medium, utm_campaign, and landing_page as separate fields on customer.metadata, and copy the same values into subscription.metadata when the subscription is created. Most reporting connectors surface subscription metadata natively as queryable dimensions, while customer metadata typically sits inside the customer JSON object and requires extraction work. Do this before you build any of the dashboards in this post.

The 2 SaaS marketing dashboards worth building

Once Stripe data flows into Looker Studio with the acquisition channel field aligned, these two reports change how SaaS marketing teams measure paid acquisition. Neither is a default Stripe Dashboard view, both require the metadata stamping above, and both answer questions the signup count alone hides.

Dashboard 1: Trial conversion funnel by acquisition channel

The question: of the 1,200 trial signups Meta Ads brought in last month, how many actually converted to paid by day 14, and how does that conversion rate compare to LinkedIn Ads or organic search? What is the true CAC after factoring trial-to-paid conversion, not just signup count?

Funnel stages to extract from Stripe:

  • Customers created (day zero, by acquisition channel)
  • Subscriptions with status = trialing (active trial)
  • Subscriptions where trial_end has passed and status transitioned to active (trial-to-paid conversion)
  • Subscriptions where trial_end passed and status = canceled (trial drop-off)

Columns to pull from Meta Ads, LinkedIn Ads, or Google Ads:

  • Campaign ID, daily spend, conversions reported by the platform
  • UTM source/medium on the landing page that maps to Stripe's metadata.acquisition_channel

Calculations in Looker Studio (or in the Sheet feeding it):

  • Trial conversion rate by channel: COUNT(status = active AND trial_end < today) ÷ COUNT(trial_start <= today - 14)
  • True CAC by channel: SUM(channel_spend) ÷ COUNT(active paid subscriptions from that channel)
  • CAC payback period: CAC ÷ (average MRR per customer for that channel)

Looker Studio layout:

  • Time-series chart: weekly trial signups, trial conversions, and conversion rate per channel
  • Bar chart: True CAC by channel (sorted ascending)
  • Scorecard: blended CAC payback period in months
  • Filter controls: date range, channel multi-select

What this dashboard surfaces that signup counts hide:

  • Channels with high signup volume but poor trial-to-paid conversion (your Meta Ads creative that converts to free trial signup at a great cost but where almost nobody pays)
  • Channels with low signup volume but excellent trial-to-paid conversion (the high-intent referral or comparison-site source that costs nothing and converts at 60%)
  • The actual CAC after trial drop-off, not the inflated marketing-platform CAC measured at signup

Dashboard 2: Dunning recovery by acquisition channel

The question: when a paid customer's card fails, do customers acquired through Meta Ads recover their payment at the same rate as those from LinkedIn or organic? Are you losing recoverable revenue silently to certain channels?

Data to extract from Stripe:

  • Invoice id, customer, status, due_date, amount_due, created
  • Invoice transitions: status remaining open past due_date means Stripe Smart Retries dunning is iterating on the customer's payment method
  • PaymentIntent last_payment_error.code attached to the invoice (card_declined, insufficient_funds, expired_card)
  • Final invoice status: paid (recovered), uncollectible (failed dunning), or void (canceled before recovery)
  • Subscription metadata.acquisition_channel on the parent subscription (write this at subscription creation for native dimension access)

Calculations in Looker Studio:

  • Dunning recovery rate by channel: COUNT(invoices that transitioned from open past due_date to final status paid) ÷ COUNT(invoices that stayed open past due_date at least once)
  • Lost revenue by channel: SUM(amount_due) where final status = uncollectible, grouped by channel
  • Failure reason breakdown: COUNT by last_payment_error.code

Looker Studio layout:

  • Heat map: rows = acquisition channel, columns = failure reason, cells = recovery rate
  • Bar chart: total uncollectible revenue lost by channel (last 90 days)
  • Scorecard: blended dunning recovery rate, with trend versus prior period

What this dashboard surfaces that the default Stripe reports do not:

  • Channels where customers churn through silent payment failure (your Meta retargeting audience that signs up enthusiastically, never updates a card, and quietly cancels at first failed renewal)
  • Failure reason concentration by channel (channels skewing toward expired cards versus insufficient funds tell different stories about audience quality)
  • The recoverable revenue you are leaving on the table because your dunning emails are not tuned per channel

Comparing the three methods

Aspect Manual CSV Apps Script Scheduled connector
Setup time10 min45-90 minUnder 10 min
CostFreeFreeFree tier, paid plans scale
Subscription metadata exposedNot in default exportVia expand parameterNative dimension
Cancellation reasonsPer-export filterCode field accessNative dimension
Scheduled refreshNoYes (Apps Script triggers)Yes (built in)
Multi-source joins (paid ads)ManualManualSame workbook, formula-distance
API versioning handlingNot applicableOwner pins manuallyVendor managed
Code maintenanceNoneOwnerVendor

The decision usually comes down to whether your acquisition channel is already stamped into customer.metadata and how often the dashboard refreshes. Stamped and weekly refresh: manual works. Stamped and daily refresh: Apps Script. Stamped, multi-channel join, and you want time back: scheduled connector.

Stripe quirks worth knowing

Five behaviors that affect every method and every dashboard built on top of Stripe subscription data:

  • Status transitions are not always linear. A subscription can go from trialing to active to past_due back to active (recovered dunning), then to canceled. To measure trial-to-paid conversion correctly, query the status at the moment trial_end passed, not the current status. Use a snapshot or the events log; current state alone hides the funnel.
  • Proration changes the MRR math. Mid-cycle plan changes trigger prorated invoices. If you compute MRR by summing all invoices in a month, mid-cycle upgrades or downgrades double-count or double-discount. Use subscription.plan.amount at the period boundary instead of invoice sums.
  • Trial extensions silently move trial_end. Customer support team granting a one-week trial extension shifts the trial_end date on the subscription object. Your "did this customer convert by day 14" query needs to anchor on trial_start plus a fixed offset, not on whatever trial_end is right now.
  • Test mode subscriptions look identical to live. If your reporting accidentally points at the test API key, the data looks plausible and your dashboard quietly reports test subscriptions. Audit which key prefix your connector uses on first setup; many post-mortems end here.
  • Customer.metadata is unstructured. Stripe does not validate the keys or values you write into metadata. If your signup form writes source in some flows and acquisition_channel in others, your dashboard sees them as different fields. Standardize the metadata key names at the signup form layer first.

Common errors and how to read them

401 unauthorized: the restricted API key is invalid, revoked, or missing the Bearer prefix in the Authorization header. Also fires if you used a rk_test_ key against live data or vice versa.

403 forbidden: the restricted key was created without the required scope on the object you are requesting. Edit the key in Dashboard, expand scopes (read access on the relevant object types), save, retry.

429 too many requests: rate limit hit. Stripe returns a 429 with no Retry-After header by default; implement exponential backoff starting at 1 second and doubling up to 32 seconds. Rare for read workflows; common if you accidentally loop without pagination.

400 bad request with parameter error: usually an unknown parameter or a malformed expand[] path. Stripe's error message tells you which parameter; consult the API reference for the correct shape.

Empty data array on subscriptions: common cause is filtering by a status that does not exist (typos like active_status instead of active), or pulling from test mode where you have no real data. Verify the key prefix and the status spelling.

FAQ

Can Looker Studio connect to Stripe natively in 2026?
Looker Studio has no first-party native Stripe connector. The Looker Studio Connector Gallery contains Partner Connectors built by third parties (typically priced at $5-25 per user per month) that bridge Stripe to Looker Studio. The alternative is to land Stripe data into Google Sheets or BigQuery first, then point Looker Studio at that data source.

How do I track the acquisition channel for a Stripe customer?
Write utm_source, utm_medium, utm_campaign, and a normalized acquisition_channel field into customer.metadata at the moment of customer creation, and copy the same values into subscription.metadata when the subscription is created. Stripe preserves both forever. Most reporting connectors surface subscription metadata as native queryable dimensions, while customer metadata typically sits inside the customer JSON object. Writing to both gives you native dimension access in the dashboard without JSON extraction. This is the single most important fix for SaaS marketing attribution.

What is the difference between subscription status and invoice status?
Subscription status describes the recurring billing relationship (trialing, active, past_due, canceled, unpaid, incomplete). Invoice status describes a single billing event within that relationship (draft, open, paid, void, uncollectible). A subscription can be active while its current invoice is open (unpaid but not yet failed); a subscription becomes past_due only after dunning attempts.

How can I join Stripe data with Meta Ads spend in Looker Studio?
Bring both into the same data source layer (Looker Studio with a partner connector, or Google Sheets/BigQuery with a connector landing both). Then create a calculated field in Looker Studio that joins on the channel dimension (typically the normalized acquisition_channel stamped in Stripe metadata, matched against utm_source in Meta Ads). For small datasets, a blend in Looker Studio works; for larger volumes, pre-aggregate in the data source layer.

How do I track trial-to-paid conversion in Stripe?
For each subscription created in a given month, snapshot the status at the moment trial_end passes. A subscription with status active at that point converted; one with canceled or incomplete did not. The Stripe Events log preserves these transitions; the current state of the subscription object does not. Most teams query events or maintain a daily snapshot of subscription state.

Why is my dunning recovery rate lower than Stripe's published benchmark?
Stripe publishes blended recovery benchmarks across all merchants. Your rate varies dramatically by audience quality (which is what acquisition channel reveals), card mix (corporate cards recover at higher rates than personal), geography (US/EU recover differently), and whether you have Smart Retries enabled in Billing settings. Segmenting recovery by channel reveals where your audience quality is leaking.

Conclusion

The three methods to pull Stripe into Looker Studio in 2026 sit on a spectrum: manual CSV for one-off audits, Apps Script for free automation if your team can maintain code and the metadata fields, scheduled connector for hands-off SaaS marketing dashboards across multiple paid channels. The right method depends on whether your signup form is already stamping acquisition channel into customer.metadata and how often the funnel needs to refresh.

But the methods are means, not the end. The two dashboards (trial conversion funnel by channel and dunning recovery by channel) are the work that changes how SaaS marketers measure paid acquisition. Both require the metadata stamping to be in place at the signup form, both require Stripe data joined to your paid media spend, and both answer the question that signup counts alone never could in 2026: which channels actually pay back, and on what timeline.

Fix the metadata stamping. Pull the Stripe data into Looker Studio. Build the two dashboards. Start a free Dataslayer trial if you want to skip the API maintenance and the metadata extraction work, and get straight to the dashboards.

HOW CAN WE HELP?

Knowledge baseSupport ticketContact

RELATED POST

Stripe to Looker Studio in 2026: Trial Conversion Funnel and Dunning Recovery Dashboards for SaaS Marketers

The Best Data Visualization Tools for Marketing Teams in 2026: A Connector-First Buyer's Guide

How to Connect Klaviyo to Google Sheets for Ecommerce Email and SMS Attribution

Our Partners

Google Cloud Partner
Microsoft Partner