Looker Studio Integration
The Looker Studio integration lets you build custom dashboards and reports in Google Looker Studio using your GrowPanel subscription data. Visualize MRR trends, customer counts, churn rates, and more — all in a tool your team may already be using.
GrowPanel provides a read-only API key that you use to pull data into Looker Studio. There are two ways to connect, depending on your preference.
Prerequisites
Before you start, enable the integration in GrowPanel:
- Go to Settings > Integrations
- Find the Looker Studio card and click Enable
- Copy the API Key and API Base URL from the modal — you'll need them in the steps below
The API key is only shown once when you enable the integration. If you lose it, click Remove on the Looker Studio card and enable it again to generate a new key.
Method 1: Via Google Sheets (recommended)
This is the easiest approach and works well for most teams. You use a small script to pull GrowPanel data into a Google Sheet, then connect that sheet to Looker Studio. The data refreshes automatically on a schedule you choose.
Step 1 — Create a Google Sheet
- Open Google Sheets and create a new spreadsheet
- Rename it to something descriptive, like "GrowPanel — MRR Data"
Step 2 — Add the import script
- In your spreadsheet, go to Extensions > Apps Script
- Delete any existing code and paste the following:
const API_KEY = 'YOUR_API_KEY_HERE';
const BASE_URL = 'https://api.growpanel.io';
function importMRR() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('MRR')
|| SpreadsheetApp.getActiveSpreadsheet().insertSheet('MRR');
fetchAndWrite(sheet, '/reports/mrr');
}
function importCustomers() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Customers')
|| SpreadsheetApp.getActiveSpreadsheet().insertSheet('Customers');
fetchAndWrite(sheet, '/customers');
}
function importSummary() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Summary')
|| SpreadsheetApp.getActiveSpreadsheet().insertSheet('Summary');
fetchAndWrite(sheet, '/reports/summary');
}
function importAll() {
importMRR();
importCustomers();
importSummary();
}
function fetchAndWrite(sheet, endpoint) {
const options = {
method: 'get',
headers: { 'Authorization': 'Bearer ' + API_KEY },
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(BASE_URL + endpoint, options);
if (response.getResponseCode() !== 200) {
Logger.log('Error fetching ' + endpoint + ': ' + response.getContentText());
return;
}
const json = JSON.parse(response.getContentText());
const data = json.result || json;
if (!Array.isArray(data) || data.length === 0) {
Logger.log('No data returned for ' + endpoint);
return;
}
const headers = Object.keys(data[0]);
const rows = data.map(row => headers.map(h => row[h] ?? ''));
sheet.clear();
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
if (rows.length > 0) {
sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
}
Logger.log('Imported ' + rows.length + ' rows into ' + sheet.getName());
}- Replace
YOUR_API_KEY_HEREwith the API key you copied from GrowPanel - Click Save (or Ctrl+S)
Step 3 — Run the script
- In the Apps Script editor, select importAll from the function dropdown
- Click Run
- The first time, Google will ask you to authorize the script — click through the prompts
- Switch back to your spreadsheet — you should see sheets named "MRR", "Customers", and "Summary" filled with data
Step 4 — Set up automatic refresh
- In the Apps Script editor, click the clock icon on the left sidebar (Triggers)
- Click + Add Trigger
- Set it up:
- Function: importAll
- Event source: Time-driven
- Type: Hour timer (or Day timer for daily updates)
- Interval: Every 4 hours (or your preference)
- Click Save
Your sheet will now refresh automatically.
Step 5 — Connect the sheet to Looker Studio
- Open Looker Studio
- Click Create > Data source
- Select the Google Sheets connector (built-in, no installation needed)
- Find and select your spreadsheet
- Choose the sheet tab you want (e.g., "MRR")
- Click Connect
You can now use this data source in any Looker Studio report. Repeat for each sheet tab you want to use.
Method 2: Community Connector (advanced)
This method creates a direct, live connection between Looker Studio and GrowPanel's API — no intermediate spreadsheet needed. It requires deploying a Google Apps Script project as a Looker Studio connector.
Step 1 — Create the connector project
- Go to Google Apps Script and click New project
- Rename the project to "GrowPanel Connector"
- Delete any existing code in
Code.gsand paste the following:
var cc = DataStudioApp.createCommunityConnector();
function getAuthType() {
return cc.newAuthTypeResponse()
.setAuthType(cc.AuthType.KEY)
.setHelpUrl('https://growpanel.io/docs/settings/integrations/looker-studio/')
.build();
}
function setCredentials(request) {
PropertiesService.getUserProperties().setProperty('apiKey', request.key);
return { errorCode: 'NONE' };
}
function isAuthValid() {
var key = PropertiesService.getUserProperties().getProperty('apiKey');
if (!key) return false;
try {
var response = UrlFetchApp.fetch('https://api.growpanel.io/reports/summary', {
headers: { 'Authorization': 'Bearer ' + key },
muteHttpExceptions: true
});
return response.getResponseCode() === 200;
} catch (e) {
return false;
}
}
function resetAuth() {
PropertiesService.getUserProperties().deleteProperty('apiKey');
}
function getConfig() {
var config = cc.getConfig();
config.newSelectSingle()
.setId('endpoint')
.setName('Data to import')
.setHelpText('Choose which GrowPanel data to load')
.setAllowOverride(true)
.addOption(config.newOptionBuilder().setLabel('MRR over time').setValue('/reports/mrr'))
.addOption(config.newOptionBuilder().setLabel('MRR summary').setValue('/reports/summary'))
.addOption(config.newOptionBuilder().setLabel('Customers').setValue('/customers'))
.addOption(config.newOptionBuilder().setLabel('Movement table').setValue('/reports/movement-table'))
.addOption(config.newOptionBuilder().setLabel('Plans').setValue('/plans'))
.addOption(config.newOptionBuilder().setLabel('Leads').setValue('/reports/leads'));
config.setDateRangeRequired(false);
return config.build();
}
function getSchema(request) {
var key = PropertiesService.getUserProperties().getProperty('apiKey');
var endpoint = request.configParams.endpoint || '/reports/summary';
var data = fetchData(key, endpoint);
if (!data || data.length === 0) {
return { schema: [] };
}
var fields = Object.keys(data[0]).map(function(name) {
var sample = data[0][name];
var field = cc.newField()
.setId(name)
.setName(name);
if (typeof sample === 'number') {
field.setType(cc.FieldType.NUMBER);
} else {
field.setType(cc.FieldType.TEXT);
}
return field;
});
return cc.newGetSchemaResponse().setFields(fields).build();
}
function getData(request) {
var key = PropertiesService.getUserProperties().getProperty('apiKey');
var endpoint = request.configParams.endpoint || '/reports/summary';
var data = fetchData(key, endpoint);
var requestedFieldNames = request.fields.map(function(f) { return f.name; });
var rows = data.map(function(row) {
return {
values: requestedFieldNames.map(function(name) {
var val = row[name];
return val !== undefined && val !== null ? val : '';
})
};
});
var fields = request.fields.map(function(f) {
var sample = data.length > 0 ? data[0][f.name] : '';
var field = cc.newField()
.setId(f.name)
.setName(f.name);
if (typeof sample === 'number') {
field.setType(cc.FieldType.NUMBER);
} else {
field.setType(cc.FieldType.TEXT);
}
return field;
});
return cc.newGetDataResponse()
.setFields(fields)
.addAllRows(rows)
.build();
}
function fetchData(apiKey, endpoint) {
var response = UrlFetchApp.fetch('https://api.growpanel.io' + endpoint, {
headers: { 'Authorization': 'Bearer ' + apiKey },
muteHttpExceptions: true
});
if (response.getResponseCode() !== 200) {
cc.newUserError()
.setText('API returned status ' + response.getResponseCode())
.throwException();
}
var json = JSON.parse(response.getContentText());
return json.result || json;
}Step 2 — Update the manifest
- In the left sidebar, click Project Settings (gear icon)
- Check Show "appsscript.json" manifest file in editor
- Go back to the editor and open
appsscript.json - Replace its contents with:
{
"timeZone": "America/New_York",
"dependencies": {},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"dataStudio": {
"name": "GrowPanel",
"description": "Connect GrowPanel subscription analytics to Looker Studio",
"company": "GrowPanel",
"logoUrl": "https://growpanel.io/images/growpanel-icon.png",
"addonUrl": "https://growpanel.io/docs/settings/integrations/looker-studio/",
"supportUrl": "https://growpanel.io/docs/settings/integrations/looker-studio/"
}
}- Click Save
Step 3 — Deploy the connector
- Click Deploy > New deployment
- Click the gear icon next to "Select type" and choose Add-on
- Add a description (e.g., "GrowPanel connector v1")
- Click Deploy
- Copy the Deployment ID — you'll need it next
Step 4 — Use the connector in Looker Studio
- Open Looker Studio
- Click Create > Data source
- Search for "GrowPanel" in the connector list, or click Build your own and enter your Deployment ID
- When prompted, paste your GrowPanel API key
- Choose which data to import (MRR over time, Customers, etc.)
- Click Connect
You now have a live data source that Looker Studio queries directly from GrowPanel's API.
Available data
Both methods give you access to the same GrowPanel API endpoints. Here are the most useful ones for reporting:
| Endpoint | Description | Example fields |
|---|---|---|
/reports/mrr | MRR over time | date, mrr, customers |
/reports/summary | Current period summary | new_mrr, churned_mrr, net_mrr, total_mrr |
/customers | Customer list | name, email, status, current_mrr, plan |
/reports/movement-table | MRR movements by month | date, new, expansion, contraction, churn, reactivation |
/reports/leads | Trial and lead metrics | date, new_leads, conversions |
/plans | Active plans | name, billing_freq, currency |
For the complete list, see the API reference.
Refreshing data
- Google Sheets method: Data refreshes on the schedule you set in Apps Script Triggers (e.g., every 4 hours). Looker Studio picks up changes automatically when the sheet updates.
- Community Connector method: Looker Studio caches data for up to 15 minutes by default. You can click the refresh icon in any report to fetch the latest data.
Revoking access
To disconnect:
- Go to Settings > Integrations in GrowPanel
- Click Remove on the Looker Studio card
This revokes the API key immediately. Any connected Looker Studio reports or Google Sheets scripts using that key will stop receiving data. You can enable the integration again at any time to generate a new key.
Troubleshooting
| Issue | Solution |
|---|---|
| "Authorization failed" in Looker Studio | Check that you pasted the full API key, including all three dot-separated parts |
| Google Sheets script returns no data | Open Apps Script, run importAll manually, and check the Execution log for errors |
| Data looks stale in Looker Studio | Click the refresh icon in your report, or check that your Sheets trigger is running |
| Lost your API key | Click Remove on the Looker Studio card in GrowPanel, then click Enable to generate a new key |
| "API returned status 401" | Your API key may have been revoked. Generate a new one in GrowPanel |
Related pages
- Integrations overview - How integrations work
- API reference - Full list of available endpoints
- Webhooks - Send data to custom endpoints
- Exports - CSV export of customers and movements