Self-Hosting Analytics
The Supabase Analytics server is a Logflare self-hostable instance that manages the ingestion and query pipelines for searching and aggregating structured analytics events.
When running the Analytics server, the logging experience matching that of the Supabase Platform is available in Studio. However, log content and metadata can differ from the Supabase Platform - see Differences from the Supabase platform below.
Locally running logs and analytics are supported in two separate setups:
- Local development & CLI - a local Supabase stack managed with the Supabase CLI (
supabase start). - Self-hosted Supabase - the full stack on your own infrastructure with Docker Compose. Logs & Analytics are optional and are not started by default.
The sections below cover backend options and Logflare configuration. For self-hosted Supabase, see the installation and configuration guide.
Logflare Technical Docs
All Logflare technical documentation is available at https://docs.logflare.app.
Supported backends#
The Analytics server supports either Postgres or BigQuery as the backend. Both Local development & CLI and self-hosted Supabase use the Postgres backend out of the box.
When using the BigQuery backend, a BigQuery dataset is created in the provided Google Cloud project, and tables are created for each source. Log events are streamed into each table, and all queries generated by Studio or by the Logs Explorer are executed against the BigQuery API. This backend requires internet access to work, and cannot be run fully locally.
When using the Postgres backend, tables are created for each source within the provided schema. Log events received by Logflare are inserted directly into the respective tables. All BigQuery-dialect SQL queries from Studio are handled by a translation layer within the Analytics server. This translation layer translates the query to Postgres dialect, and then executes it against the Postgres database.
The Postgres backend is not yet optimized for a high volume of inserts, or for heavy query usage. Today the translation layer only handles a limited subset of the BigQuery dialect. As such, the Log Explorer may produce errors for more advanced queries when using the Postgres Backend.
Getting started#
The Postgres backend is recommended when familiarizing and experimenting. For production self-hosting, we recommend the BigQuery backend. See the notes below for more information.
Local development & CLI#
With the Supabase CLI, run supabase start to bring up a local stack. Logs use the Postgres backend by default and are stored in the _analytics schema. Docker socket access may need manual configuration on some platforms - see the Access your project's services (the Analytics tab).
The Supabase CLI is intended for local development only. The local analytics service uses predefined, publicly known access tokens and has no protection against external traffic. Never run the CLI stack on a publicly accessible or untrusted network.
Self-hosted Supabase#
Self-hosted Supabase does not include Logs & Analytics in the default Docker Compose configuration. You must first install and secure the base stack - generate secrets, configure URLs, and set a Studio password - as described in Self-Hosting with Docker.
Do not start the stack with placeholder values from .env.example.
After the base stack is configured, enable Logs & Analytics from your project directory (the directory containing docker-compose.yml):
1sh run.sh config add logs && \2sh run.sh startThis layers docker-compose.logs.yml on top of the base configuration and starts two additional services (analytics and vector).
See Enabling analytics in the self-hosting guide for more context.
Required Logflare configuration#
The following environment variables are always required for the supabase/logflare image:
docker-compose.logs.yml
1analytics:2 environment:3 # Enable single-tenant mode for Logflare4 LOGFLARE_SINGLE_TENANT: 'true'5 # Seed Supabase-related metadata6 LOGFLARE_SUPABASE_MODE: 'true'For all other configuration environment variables, refer to the Logflare self-hosting documentation.
Using the Postgres backend#
Local development & CLI#
The CLI uses the Postgres backend by default. No additional configuration is needed.
Self-hosted Supabase#
The docker-compose.logs.yml override uses the Postgres backend by default.
Configuration and requirements#
The following environment variables control the Postgres backend (set in docker-compose.logs.yml):
POSTGRES_BACKEND_URL: Required. Connection string to the Postgres database.POSTGRES_BACKEND_SCHEMA: Optional. Schema used to store log data (default:_analytics).
Using the BigQuery backend#
The BigQuery backend is a more robust and scalable backend option that is battle-tested and production ready. Use this backend if you intend to have heavy logging usage and require advanced querying features such as the Logs Explorer.
Requirements#
Using the BigQuery backend requires:
- A Google Cloud project with billing enabled
- The project ID
- The project number
- A service account JSON key
A valid billing account is required for BigQuery streaming inserts.
Google Cloud Console setup#
- Open Google Cloud Console and select or create the project you want to use for analytics.
- Confirm billing is enabled on that project (Billing - link the project to a billing account if needed).
- Go to IAM & Admin > Service Accounts and click Create service account (for example,
supabase-analytics). - On Permissions, grant BigQuery Admin to keep setup simple. Skip Principals with access. Alternatively, grant only the specific permissions listed below instead of the admin role.
- Open the service account, then Keys (or Actions > Manage keys from the list view). Click Add key > Create new key, choose JSON, and download the key file.
- Go to APIs & Services > Library, search for Cloud Resource Manager API, open it, and click Enable. Confirm the correct project is selected in the project picker at the top. You can also enable it directly:
https://console.developers.google.com/apis/api/cloudresourcemanager.googleapis.com/overview?project=YOUR_PROJECT_ID(replaceYOUR_PROJECT_ID). - Go to Cloud overview > Dashboard (home dashboard for the project) and copy the Project ID and Project number. Confirm the project picker at the top shows the same project you configured above.
- Save the downloaded JSON key as
gcloud.jsonin your self-hosted Supabase project directory (the directory that containsdocker-compose.yml.
Do not commit gcloud.json to version control. Add it to .gitignore if needed.
Minimum BigQuery permissions
If you prefer not to use the BigQuery Admin role, the service account needs at least the following permissions:
bigquery.datasets.create,bigquery.datasets.get,bigquery.datasets.getIamPolicy,bigquery.datasets.updatebigquery.jobs.createbigquery.routines.create,bigquery.routines.updatebigquery.tables.create,bigquery.tables.delete,bigquery.tables.get,bigquery.tables.getData,bigquery.tables.update,bigquery.tables.updateData
Self-hosted Supabase configuration#
Complete Self-Hosting with Docker first. Enable the logs override, then switch the analytics service in docker-compose.logs.yml from Postgres to BigQuery.
1. Set Google Cloud variables in .env
Add your project values under the Analytics section (do not leave the .env.example placeholders):
1############2# Logs and Analytics3############45# Google Cloud Project details6GOOGLE_PROJECT_ID=your-project-id7GOOGLE_PROJECT_NUMBER=1234567890122. Mount the service account key and switch the analytics backend
In docker-compose.logs.yml, under the analytics service:
- Remove or comment out
POSTGRES_BACKEND_URLandPOSTGRES_BACKEND_SCHEMA. - Uncomment
GOOGLE_PROJECT_IDandGOOGLE_PROJECT_NUMBER. - Uncomment the
volumesblock and bind-mountgcloud.jsonfrom your project directory.
Example:
docker-compose.logs.yml
1analytics:2 environment:3 GOOGLE_PROJECT_ID: ${GOOGLE_PROJECT_ID}4 GOOGLE_PROJECT_NUMBER: ${GOOGLE_PROJECT_NUMBER}5 volumes:6 - ./gcloud.json:/opt/app/rel/logflare/bin/gcloud.json:ro,z3. Start the stack
From your project directory:
1sh run.sh config add logs && \2sh run.sh startLog collection and routing with Vector#
In the self-hosted Docker Compose setup, Vector is used for the logging pipeline when the docker-compose.logs.yml override is enabled. Log events are forwarded to the Analytics API for ingestion.
Please refer to the Vector configuration file when customizing your own setup.
You must ensure that each payload matches the event shape produced by the Vector transforms. Logs Explorer in Studio expects the fields below when querying Analytics sources:
| Field | Description |
|---|---|
event_message | The log message displayed in Studio. |
timestamp | The event timestamp. If omitted, Logflare assigns an ingestion timestamp. |
metadata | A JSON object with service-specific fields used by the Logs UI. For example, API logs include request and response metadata, while database logs include parsed Postgres severity metadata. |
When adding a custom Vector source, map your service logs to this shape before sending them to http://analytics:4000/api/logs?source_name=<source-name>. Reuse the existing source names in vector.yml if you want the logs to appear in the built-in Studio Logs panels.
Differences from the Supabase platform#
API logs rely on the locally running API gateway (Kong) instead of the Supabase Cloud API Gateway. Logs from Kong are not enriched with platform-only data.
Within self-hosted Supabase (with the logs override enabled), container logs are routed to Logflare via Vector. As Kong routes API requests to PostgREST, self-hosted and local development & CLI deployments produce Kong request logs rather than the platform API gateway logs.
This results in differences in log event metadata between your own infrastructure and the Supabase Platform.
Recommendations for production#
When running a self-hosted instance of Logflare in production, we recommend the following.
Set unique access tokens#
LOGFLARE_PUBLIC_ACCESS_TOKEN and LOGFLARE_PRIVATE_ACCESS_TOKEN must be set to unique, randomly generated values. Never run with the placeholder or default values.
In a self-hosted Supabase configuration, these tokens are generated automatically when you run sh utils/generate-keys.sh during initial setup.
Restrict network access to Logflare#
Self-hosted Logflare has UI authentication disabled.
The /dashboard path is publicly accessible by default and must be restricted at the network level. If you need dashboard access for managing sources, place it behind a VPN or other secure access layer.
Direct access to the Logflare's container port 4000 is intentionally not exposed in the default self-hosted Supabase configuration - Logflare is only reachable through the API gateway (Kong). Do not re-expose this port directly unless required.
Use a different Postgres Database to store Logflare data#
Logflare requires a Postgres database to function. However, if there is an issue with you self-hosted Postgres service, you would not be able to debug it as it would also bring down Logflare.
The self-hosted Docker example is a minimal reference for running the entire stack; it is not recommended to use the same Postgres instance for both production workloads and observability data.
Use BigQuery as the Logflare backend#
The current Postgres Ingestion backend isn't optimized for production usage. We recommend using BigQuery for more heavy use cases.
We recommend using the BigQuery backend for production environments as it offers better scaling and querying/debugging experiences.
Rotate encryption keys regularly#
The Logflare server uses the a Base64 encryption key optionally set via the LOGFLARE_DB_ENCRYPTION_KEY environment variable to perform encryption at rest for sensitive database columns.
To perform encryption key rotation, move the retired key to the LOGFLARE_DB_ENCRYPTION_KEY_RETIRED environment variable, and replace the LOGFLARE_DB_ENCRYPTION_KEY environement variable with the new key. Perform a server restart and check info logs for the migration to be detected and performed.
Once migration is complete, you can safely remove the retired key.
Client libraries#
- JavaScript - Pino Transport
- Elixir
- Elixir - Logger Backend
- Erlang
- Erlang - Lager Backend
- Cloudflare Worker
Integrations#
Additional links#
List endpoints
/api/endpointsResponse codes
- 200
Response (200)
1[2 {3 "cache_duration_seconds": 42,4 "enable_auth": true,5 "inserted_at": "2021-12-31T23:34:00Z",6 "max_limit": 42,7 "name": "lorem",8 "proactive_requerying_seconds": 42,9 "query": "lorem",10 "sandboxable": true,11 "source_mapping": {},12 "token": "lorem",13 "updated_at": "2021-12-31T23:34:00Z"14 }15]Create endpoint
/api/endpointsBody
- cache_duration_secondsOptionalinteger
- enable_authOptionalboolean
- inserted_atOptionalstring
- max_limitOptionalinteger
- nameRequiredstring
- proactive_requerying_secondsOptionalinteger
- queryRequiredstring
- sandboxableOptionalboolean
- source_mappingOptionalobject
- tokenOptionalstring
- updated_atOptionalstring
Response codes
- 201
- 404
Response (201)
1{2 "cache_duration_seconds": 42,3 "enable_auth": true,4 "inserted_at": "2021-12-31T23:34:00Z",5 "max_limit": 42,6 "name": "lorem",7 "proactive_requerying_seconds": 42,8 "query": "lorem",9 "sandboxable": true,10 "source_mapping": {},11 "token": "lorem",12 "updated_at": "2021-12-31T23:34:00Z"13}Delete endpoint
/api/endpoints/{token}Path parameters
- tokenRequiredstring
Endpoint Token
Response codes
- 204
- 404
Response (204)
1{}Fetch endpoint
/api/endpoints/{token}Path parameters
- tokenRequiredstring
Endpoint Token
Response codes
- 200
- 404
Response (200)
1{2 "cache_duration_seconds": 42,3 "enable_auth": true,4 "inserted_at": "2021-12-31T23:34:00Z",5 "max_limit": 42,6 "name": "lorem",7 "proactive_requerying_seconds": 42,8 "query": "lorem",9 "sandboxable": true,10 "source_mapping": {},11 "token": "lorem",12 "updated_at": "2021-12-31T23:34:00Z"13}Update endpoint
/api/endpoints/{token}Path parameters
- tokenRequiredstring
Endpoint Token
Body
- cache_duration_secondsOptionalinteger
- enable_authOptionalboolean
- inserted_atOptionalstring
- max_limitOptionalinteger
- nameRequiredstring
- proactive_requerying_secondsOptionalinteger
- queryRequiredstring
- sandboxableOptionalboolean
- source_mappingOptionalobject
- tokenOptionalstring
- updated_atOptionalstring
Response codes
- 201
- 404
Response (201)
1{2 "cache_duration_seconds": 42,3 "enable_auth": true,4 "inserted_at": "2021-12-31T23:34:00Z",5 "max_limit": 42,6 "name": "lorem",7 "proactive_requerying_seconds": 42,8 "query": "lorem",9 "sandboxable": true,10 "source_mapping": {},11 "token": "lorem",12 "updated_at": "2021-12-31T23:34:00Z"13}List sources
/api/sourcesResponse codes
- 200
Response (200)
1{2 "items": {3 "properties": {4 "api_quota": {5 "type": "integer"6 },7 "bigquery_table_ttl": {8 "type": "integer"9 },10 "bq_table_id": {11 "type": "string"12 },13 "bq_table_schema": {14 "type": "object"15 },16 "custom_event_message_keys": {17 "type": "string"18 },19 "favorite": {20 "type": "boolean"21 },22 "has_rejected_events": {23 "type": "boolean"24 },25 "id": {},26 "inserted_at": {27 "format": "date-time",28 "type": "string"29 },30 "metrics": {31 "type": "object"32 },33 "name": {34 "type": "string"35 },36 "notifications": {37 "items": {38 "properties": {39 "other_email_notifications": {40 "type": "string"41 },42 "team_user_ids_for_email": {43 "allOf": {44 "type": "string"45 },46 "type": "array"47 },48 "team_user_ids_for_schema_updates": {49 "allOf": {50 "type": "string"51 },52 "type": "array"53 },54 "team_user_ids_for_sms": {55 "allOf": {56 "type": "string"57 },58 "type": "array"59 },60 "user_email_notifications": {61 "type": "boolean"62 },63 "user_schema_update_notifications": {64 "type": "boolean"65 },66 "user_text_notifications": {67 "type": "boolean"68 }69 },70 "title": "Notification",71 "type": "object"72 },73 "type": "array"74 },75 "public_token": {76 "type": "string"77 },78 "slack_hook_url": {79 "type": "string"80 },81 "token": {82 "type": "string"83 },84 "updated_at": {85 "format": "date-time",86 "type": "string"87 },88 "webhook_notification_url": {89 "type": "string"90 }91 },92 "required": [93 "name"94 ],95 "title": "Source",96 "type": "object"97 },98 "type": "array"99}Create source
/api/sourcesBody
- api_quotaOptionalinteger
- bigquery_table_ttlOptionalinteger
- bq_table_idOptionalstring
- bq_table_schemaOptionalobject
- custom_event_message_keysOptionalstring
- favoriteOptionalboolean
- has_rejected_eventsOptionalboolean
- idOptionalunknown
- inserted_atOptionalstring
- metricsOptionalobject
- nameRequiredstring
- notificationsOptionalArray<object>
- public_tokenOptionalstring
- slack_hook_urlOptionalstring
- tokenOptionalstring
- updated_atOptionalstring
- webhook_notification_urlOptionalstring
Response codes
- 201
- 404
Response (201)
1{2 "properties": {3 "api_quota": {4 "type": "integer"5 },6 "bigquery_table_ttl": {7 "type": "integer"8 },9 "bq_table_id": {10 "type": "string"11 },12 "bq_table_schema": {13 "type": "object"14 },15 "custom_event_message_keys": {16 "type": "string"17 },18 "favorite": {19 "type": "boolean"20 },21 "has_rejected_events": {22 "type": "boolean"23 },24 "id": {},25 "inserted_at": {26 "format": "date-time",27 "type": "string"28 },29 "metrics": {30 "type": "object"31 },32 "name": {33 "type": "string"34 },35 "notifications": {36 "items": {37 "properties": {38 "other_email_notifications": {39 "type": "string"40 },41 "team_user_ids_for_email": {42 "allOf": {43 "type": "string"44 },45 "type": "array"46 },47 "team_user_ids_for_schema_updates": {48 "allOf": {49 "type": "string"50 },51 "type": "array"52 },53 "team_user_ids_for_sms": {54 "allOf": {55 "type": "string"56 },57 "type": "array"58 },59 "user_email_notifications": {60 "type": "boolean"61 },62 "user_schema_update_notifications": {63 "type": "boolean"64 },65 "user_text_notifications": {66 "type": "boolean"67 }68 },69 "title": "Notification",70 "type": "object"71 },72 "type": "array"73 },74 "public_token": {75 "type": "string"76 },77 "slack_hook_url": {78 "type": "string"79 },80 "token": {81 "type": "string"82 },83 "updated_at": {84 "format": "date-time",85 "type": "string"86 },87 "webhook_notification_url": {88 "type": "string"89 }90 },91 "required": [92 "name"93 ],94 "title": "Source",95 "type": "object"96}Delete source
/api/sources/{token}Path parameters
- tokenRequiredstring
Source Token
Response codes
- 204
- 404
Response (204)
1{}Fetch source
/api/sources/{token}Path parameters
- tokenRequiredstring
Source Token
Response codes
- 200
- 404
Response (200)
1{2 "properties": {3 "api_quota": {4 "type": "integer"5 },6 "bigquery_table_ttl": {7 "type": "integer"8 },9 "bq_table_id": {10 "type": "string"11 },12 "bq_table_schema": {13 "type": "object"14 },15 "custom_event_message_keys": {16 "type": "string"17 },18 "favorite": {19 "type": "boolean"20 },21 "has_rejected_events": {22 "type": "boolean"23 },24 "id": {},25 "inserted_at": {26 "format": "date-time",27 "type": "string"28 },29 "metrics": {30 "type": "object"31 },32 "name": {33 "type": "string"34 },35 "notifications": {36 "items": {37 "properties": {38 "other_email_notifications": {39 "type": "string"40 },41 "team_user_ids_for_email": {42 "allOf": {43 "type": "string"44 },45 "type": "array"46 },47 "team_user_ids_for_schema_updates": {48 "allOf": {49 "type": "string"50 },51 "type": "array"52 },53 "team_user_ids_for_sms": {54 "allOf": {55 "type": "string"56 },57 "type": "array"58 },59 "user_email_notifications": {60 "type": "boolean"61 },62 "user_schema_update_notifications": {63 "type": "boolean"64 },65 "user_text_notifications": {66 "type": "boolean"67 }68 },69 "title": "Notification",70 "type": "object"71 },72 "type": "array"73 },74 "public_token": {75 "type": "string"76 },77 "slack_hook_url": {78 "type": "string"79 },80 "token": {81 "type": "string"82 },83 "updated_at": {84 "format": "date-time",85 "type": "string"86 },87 "webhook_notification_url": {88 "type": "string"89 }90 },91 "required": [92 "name"93 ],94 "title": "Source",95 "type": "object"96}Update source
/api/sources/{token}Path parameters
- tokenRequiredstring
Source Token
Body
- api_quotaOptionalinteger
- bigquery_table_ttlOptionalinteger
- bq_table_idOptionalstring
- bq_table_schemaOptionalobject
- custom_event_message_keysOptionalstring
- favoriteOptionalboolean
- has_rejected_eventsOptionalboolean
- idOptionalunknown
- inserted_atOptionalstring
- metricsOptionalobject
- nameRequiredstring
- notificationsOptionalArray<object>
- public_tokenOptionalstring
- slack_hook_urlOptionalstring
- tokenOptionalstring
- updated_atOptionalstring
- webhook_notification_urlOptionalstring
Response codes
- 201
- 404
Response (201)
1{2 "properties": {3 "api_quota": {4 "type": "integer"5 },6 "bigquery_table_ttl": {7 "type": "integer"8 },9 "bq_table_id": {10 "type": "string"11 },12 "bq_table_schema": {13 "type": "object"14 },15 "custom_event_message_keys": {16 "type": "string"17 },18 "favorite": {19 "type": "boolean"20 },21 "has_rejected_events": {22 "type": "boolean"23 },24 "id": {},25 "inserted_at": {26 "format": "date-time",27 "type": "string"28 },29 "metrics": {30 "type": "object"31 },32 "name": {33 "type": "string"34 },35 "notifications": {36 "items": {37 "properties": {38 "other_email_notifications": {39 "type": "string"40 },41 "team_user_ids_for_email": {42 "allOf": {43 "type": "string"44 },45 "type": "array"46 },47 "team_user_ids_for_schema_updates": {48 "allOf": {49 "type": "string"50 },51 "type": "array"52 },53 "team_user_ids_for_sms": {54 "allOf": {55 "type": "string"56 },57 "type": "array"58 },59 "user_email_notifications": {60 "type": "boolean"61 },62 "user_schema_update_notifications": {63 "type": "boolean"64 },65 "user_text_notifications": {66 "type": "boolean"67 }68 },69 "title": "Notification",70 "type": "object"71 },72 "type": "array"73 },74 "public_token": {75 "type": "string"76 },77 "slack_hook_url": {78 "type": "string"79 },80 "token": {81 "type": "string"82 },83 "updated_at": {84 "format": "date-time",85 "type": "string"86 },87 "webhook_notification_url": {88 "type": "string"89 }90 },91 "required": [92 "name"93 ],94 "title": "Source",95 "type": "object"96}List teams
/api/teamsResponse codes
- 200
Response (200)
1[2 {3 "name": "lorem",4 "team_users": [5 {6 "email": "lorem",7 "name": "lorem"8 }9 ],10 "token": "lorem",11 "user": {12 "api_key": "lorem",13 "api_quota": 42,14 "bigquery_dataset_id": "lorem",15 "bigquery_dataset_location": "lorem",16 "bigquery_project_id": "lorem",17 "company": "lorem",18 "email": "lorem",19 "email_me_product": true,20 "email_preferred": "lorem",21 "image": "lorem",22 "name": "lorem",23 "phone": "lorem",24 "provider": "lorem",25 "token": "lorem"26 }27 }28]Create Team
/api/teamsBody
- nameRequiredstring
- team_usersOptionalArray<object>
- tokenOptionalstring
- userOptionalobject
Response codes
- 201
- 404
Response (201)
1{2 "name": "lorem",3 "team_users": [4 {5 "email": "lorem",6 "name": "lorem"7 }8 ],9 "token": "lorem",10 "user": {11 "api_key": "lorem",12 "api_quota": 42,13 "bigquery_dataset_id": "lorem",14 "bigquery_dataset_location": "lorem",15 "bigquery_project_id": "lorem",16 "company": "lorem",17 "email": "lorem",18 "email_me_product": true,19 "email_preferred": "lorem",20 "image": "lorem",21 "name": "lorem",22 "phone": "lorem",23 "provider": "lorem",24 "token": "lorem"25 }26}Delete Team
/api/teams/{token}Path parameters
- tokenRequiredstring
Team Token
Response codes
- 204
- 404
Response (204)
1{}Fetch team
/api/teams/{token}Path parameters
- tokenRequiredstring
Team Token
Response codes
- 200
- 404
Response (200)
1{2 "name": "lorem",3 "team_users": [4 {5 "email": "lorem",6 "name": "lorem"7 }8 ],9 "token": "lorem",10 "user": {11 "api_key": "lorem",12 "api_quota": 42,13 "bigquery_dataset_id": "lorem",14 "bigquery_dataset_location": "lorem",15 "bigquery_project_id": "lorem",16 "company": "lorem",17 "email": "lorem",18 "email_me_product": true,19 "email_preferred": "lorem",20 "image": "lorem",21 "name": "lorem",22 "phone": "lorem",23 "provider": "lorem",24 "token": "lorem"25 }26}Update team
/api/teams/{token}Path parameters
- tokenRequiredstring
Team Token
Body
- nameRequiredstring
- team_usersOptionalArray<object>
- tokenOptionalstring
- userOptionalobject
Response codes
- 201
- 404
Response (201)
1{2 "name": "lorem",3 "team_users": [4 {5 "email": "lorem",6 "name": "lorem"7 }8 ],9 "token": "lorem",10 "user": {11 "api_key": "lorem",12 "api_quota": 42,13 "bigquery_dataset_id": "lorem",14 "bigquery_dataset_location": "lorem",15 "bigquery_project_id": "lorem",16 "company": "lorem",17 "email": "lorem",18 "email_me_product": true,19 "email_preferred": "lorem",20 "image": "lorem",21 "name": "lorem",22 "phone": "lorem",23 "provider": "lorem",24 "token": "lorem"25 }26}