# How to Integrate Twinkle Eval with Google Sheets for Automatic Result Export

> Easily integrate Twinkle Eval with Google Sheets for automatic result export. Configure your settings and run evaluations to append structured data directly to your spreadsheet. Streamline your workflow today.

- Repository: [Twinkle AI/eval](https://github.com/ai-twinkle/eval)
- Tags: how-to-guide
- Published: 2026-02-23

---

**Enable Google Sheets export in your [`config.yaml`](https://github.com/ai-twinkle/eval/blob/main/config.yaml), install the optional Google API dependencies with `pip install "twinkle-eval[google]"`, and run evaluations with `--export google_sheets` to automatically append structured results to your target spreadsheet.**

Twinkle Eval is an open-source evaluation framework from the `ai-twinkle/eval` repository that stores evaluation metrics in nested dictionaries. Integrating Twinkle Eval with Google Sheets allows you to stream these results directly into cloud spreadsheets for real-time monitoring and team collaboration. This integration leverages a modular exporter architecture that keeps authentication, data flattening, and API communication cleanly separated.

## Prerequisites and Installation

Before configuring the export pipeline, you must install the optional Google API dependencies. The core Twinkle Eval package does not include these by default to keep the base installation lightweight.

Install the Google Sheets extras using pip:

```bash
pip install "twinkle-eval[google]"

```

This installs `googleapiclient` and related authentication libraries required by `GoogleSheetsService` in [`twinkle_eval/google_services.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/google_services.py).

## Configuring Google Sheets Authentication

The integration is controlled through a dedicated configuration block in your [`config.yaml`](https://github.com/ai-twinkle/eval/blob/main/config.yaml) file. The `ConfigurationManager` class in [`twinkle_eval/config.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/config.py) validates this section via `ConfigurationManager._validate_google_sheets_config` (lines 30-46).

Add the following structure to your configuration:

```yaml
google_services:
  google_sheets:
    enabled: true
    auth_method: service_account  # or "oauth"

    credentials_file: "gcs_credentials.json"
    spreadsheet_id: "1A2b3C4d5E6f7G8h9I0jK"
    sheet_name: "Results"  # Optional; defaults to "Results"

```

The `auth_method` parameter supports **service account** authentication for automated CI/CD pipelines or **OAuth** for interactive user flows. The `spreadsheet_id` targets the specific Google Sheet where results will append.

## Architecture of the Export Pipeline

Twinkle Eval implements a clean separation of concerns across four main components to handle Google Sheets export:

- **`ConfigurationManager`** ([`twinkle_eval/config.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/config.py)): Loads and validates the `google_services` configuration, ensuring credentials and spreadsheet IDs are present before execution.

- **`GoogleSheetsService`** ([`twinkle_eval/google_services.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/google_services.py), lines 71-102): Wraps the official Google Sheets API client. It handles authentication caching and provides two critical methods: `_ensure_header_exists` to initialize the header row if missing, and `append_results_to_sheet` to write 2D row data to the target worksheet.

- **`GoogleSheetsExporter`** ([`twinkle_eval/results_exporters.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/results_exporters.py), lines 71-115): Implements the `ResultsExporter` abstract base class. It transforms the internal nested `results` dictionary into a flat tabular structure via `_flatten_results`, then delegates API calls to `GoogleSheetsService`.

- **`ResultsExporterFactory`** ([`twinkle_eval/results_exporters.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/results_exporters.py), lines 96-133): Lazily instantiates the `GoogleSheetsExporter` only when requested, avoiding circular imports and keeping startup time fast. The factory method `export_results` coordinates the entire export workflow.

- **`TwinkleEvalRunner`** ([`twinkle_eval/cli.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/cli.py)): The CLI entry point that parses the `--export` flag and passes the format list to the factory.

During execution, the runner finishes evaluation, builds the final `results` dictionary, and triggers the factory. The exporter flattens the data, and the service handles authentication, header verification, and row appending in a single atomic flow.

## Exporting Results via the Command Line

The simplest way to enable automatic export is through the CLI. After configuring [`config.yaml`](https://github.com/ai-twinkle/eval/blob/main/config.yaml), append `google_sheets` to your export formats:

```bash
twinkle-eval --config config.yaml --export json google_sheets

```

The `--export` flag forwards the list `["json", "google_sheets"]` to `ResultsExporterFactory.export_results` (source lines 53-60 in [`twinkle_eval/results_exporters.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/results_exporters.py)). The factory lazily loads the Google Sheets exporter and streams results directly to the configured spreadsheet, returning the sheet URL upon completion.

## Programmatic Integration with the Python API

For custom workflows or Jupyter notebooks, you can trigger exports manually via the Python API without using the CLI wrapper.

### Using TwinkleEvalRunner

```python
from twinkle_eval import TwinkleEvalRunner

# Initialize with configuration

runner = TwinkleEvalRunner("config.yaml")
runner.initialize()

# Run evaluation and export

results = runner.run_evaluation(export_formats=["google_sheets"])

```

This approach automatically passes the loaded configuration to the exporter factory.

### Direct Factory Access

For scripts that already possess a populated `results` dictionary, instantiate the exporter directly:

```python
from twinkle_eval.results_exporters import ResultsExporterFactory

google_cfg = {
    "credentials_file": "gcs_credentials.json",
    "spreadsheet_id": "1A2b3C4d5E6f7G8h9I0jK",
    "sheet_name": "EvalRun",
    "enabled": True,
    "auth_method": "service_account"
}

exporter = ResultsExporterFactory.create_exporter("google_sheets", google_cfg)
sheet_url = exporter.export(results, "dummy_path")  # path argument is ignored

print("Results written to:", sheet_url)

```

The `GoogleSheetsExporter.export` method (lines 94-115 in [`twinkle_eval/results_exporters.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/results_exporters.py)) builds the row structure and delegates to `GoogleSheetsService.append_results_to_sheet`, returning the public URL of the updated spreadsheet.

## Summary

- Install Google API support with `pip install "twinkle-eval[google]"` before attempting export.
- Define the `google_services.google_sheets` block in [`config.yaml`](https://github.com/ai-twinkle/eval/blob/main/config.yaml) with valid `credentials_file` and `spreadsheet_id` values.
- `ConfigurationManager` validates your Google Sheets configuration at startup to fail fast on missing credentials.
- `ResultsExporterFactory` lazily loads `GoogleSheetsExporter` to avoid unnecessary imports when the feature is unused.
- The `GoogleSheetsService` class in [`twinkle_eval/google_services.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/google_services.py) manages OAuth flows, token caching, and header initialization automatically.
- Export via CLI using `--export google_sheets` or programmatically via `ResultsExporterFactory.export_results()`.

## Frequently Asked Questions

### What authentication methods does Twinkle Eval support for Google Sheets?

Twinkle Eval supports both **service account** and **OAuth 2.0** authentication methods, specified via the `auth_method` key in [`config.yaml`](https://github.com/ai-twinkle/eval/blob/main/config.yaml). Service accounts are ideal for automated CI/CD pipelines, while OAuth suits interactive local development. The `GoogleSheetsService` class handles token caching and refresh logic transparently.

### Can I export to Google Sheets and local JSON simultaneously?

Yes. Pass multiple formats to the `--export` CLI flag or the `export_formats` Python list. For example, `--export json google_sheets` triggers both exporters sequentially via `ResultsExporterFactory`, generating a local JSON file while appending rows to the specified Google Sheet.

### How does Twinkle Eval prevent duplicate header rows?

The `GoogleSheetsService._ensure_header_exists` method checks the target sheet for existing headers before writing data. If the header row is absent, it creates one; if present, it appends data rows immediately below. This ensures idempotent writes across multiple evaluation runs.

### Where is the nested results dictionary flattened for tabular export?

The flattening logic resides in `GoogleSheetsExporter` within [`twinkle_eval/results_exporters.py`](https://github.com/ai-twinkle/eval/blob/main/twinkle_eval/results_exporters.py). The private `_flatten_results` method converts the hierarchical evaluation metrics into a 2D list compatible with the Google Sheets API, mapping nested dictionary keys to column headers automatically.