Skip to content

Automation · Operations and reporting

Build an internal AI dashboard from Google Sheets

Build an internal AI dashboard from Google Sheets, with agreed metrics and charts, as a private snapshot you can generate again.

How do I build an AI dashboard from data I already keep in Google Sheets?

Your Met validates the Google Sheets file, tab, range and headers. It reads a visible sample only to agree on columns, units, metrics and charts, then reads the full approved range, bounded to 5,000 rows, 100 columns and 50,000 cells, as unformatted values and calculates from that result. It lists Meteor Pages to detect existing names or slugs and reduce collisions. If it finds a match, it stops and asks for a separate task; it does not update or overwrite the existing page. If the list has no match, it creates a self-contained private page and reads it back. The snapshot neither queries Sheets nor loads external scripts when opened.

What starts it

When someone asks for it

It starts when someone provides the spreadsheet, tab and range they want to visualize. It is also run manually to take a new snapshot, because the page does not query Google Sheets by itself. A new snapshot requires a separate task with another name or slug; this flow does not refresh or overwrite the previous page.

A manual task: someone on the team runs it with a button, or asks the Met for it in chat.

Who runs it

Met for analytics and internal dashboards

It has no seeded name. Its job is to turn a range the team already understands into a clear internal view, without presenting unsupported claims as findings or calling a static copy a live connection.

What you need connected

6 steps · 5 tools

The procedure, step by step

Each step shows the tool that runs. They belong to the real connector: if one of them stopped existing, this page would not build.

  1. 1

    Verify the file before reading data

    Metadata confirms the title, locale, tabs, their dimensions and named ranges. The Met then reads the header row through an explicit A1 range. The row count in metadata is grid capacity, not the number of records. The user defines the real range, and the Met stops instead of guessing when a tab or column does not match.

  2. 2

    Read a sample and agree on what to show

    A finite, explicit A1 range such as Sales!A1:F20, never whole columns, returns headers and sample rows with the sheet's visible formatting. The Met describes units, blanks and apparent types, then proposes metrics, dimensions and chart types for user approval. It does not calculate KPIs from that sample or from formatted strings, and does not invent trends, targets, periods or explanations absent from the cells.

  3. 3

    Read the complete approved range for calculations

    After approval, sheets_get reads the complete finite A1 range again with UNFORMATTED_VALUE. The local limits are 5,000 rows, 100 columns and 50,000 cells. If a range exceeds any limit, this recipe stops and asks to narrow it; it does not pretend to have read everything or improvise a rule for combining blocks. KPIs come only from this complete read and approved columns and units. Numbers are unformatted, dates may be serials and trailing blank cells may be omitted, so the Met validates types, denominators, nulls and period before producing a metric.

  4. 4

    List pages and stop on a collision

    The list returns names, slugs, ids and update dates without loading page content. This preflight reduces the risk of creating another page with the same name or slug. If one exists, the run stops and asks for a separate task; it does not call pages_get or pages_update to overwrite it. pages_list and pages_create are not atomic and do not guarantee uniqueness: another concurrent creation could still collide.

  5. 5

    Create a new page if the list shows no collision

    The creation branch stores a private page with structural HTML, presentation CSS and chart JavaScript in separate fields. Data calculated from the complete read is serialized as a snapshot inside JavaScript, without OAuth identifiers, secrets or unnecessary personal information. The view uses local HTML/CSS, DOM or Canvas 2D and no external scripts. Strings are escaped and rendered with textContent, not as trusted HTML. This recipe does not call pages_update.

  6. 6

    Read back what was stored

    After creating, pages_get retrieves the new page so its id, slug, HTML, CSS and JavaScript can be compared with the agreed delivery. This read verifies storage, not successful browser rendering or the absence of XSS. Visual and security review remains a separate check before anyone relies on the dashboard.

Before you start

What you need ready

The Met solves none of these for you. If one is missing, the automation stops there.

The limits

What this automation does NOT solve

Better said here than discovered halfway through the rollout.

FAQ

Questions about this automation

No. It is a snapshot of the values read during the run. To reflect changes, open another task, review the new sample and create a new page under a different name or slug.

Not in this recipe. pages_list detects the collision and stops before writing. Updating an existing page requires a separate task and editing flow.

The FORMATTED_VALUE sample is for understanding and agreeing on columns, not calculations. KPIs come from a second complete but bounded read of the approved range with UNFORMATTED_VALUE, so numeric values do not carry visible separators or symbols.

Only the aggregates and columns needed for the agreed metrics. Tokens, secrets and personal data with no dashboard purpose are excluded before generating HTML and JavaScript.

No. pages_get confirms the three blocks were stored. Browser review and escaping and XSS checks are separate controls that must run before anyone relies on the view.

Keep going

Other automations built on the same tools

Want this automation running on your own data?

We will show it to you with your accounts connected, not with a canned demo.