# Google Apps Script Integration

### Quick Start

#### Step 1: Open the Script Editor

1. Open your Google Sheet.
2. Go to **Extensions > Apps Script**.
3. Delete any existing code in the editor.

#### Step 2: Paste the Script

```javascript
/**
 * Fetches data from CSV Getter and writes it to the active sheet.
 * Replace ENDPOINT_URL with your actual CSV Getter endpoint URL.
 */

// ========== CONFIGURATION ==========
var ENDPOINT_URL = "https://api.csvgetter.com/YOUR_ENDPOINT_ID";
var SHEET_NAME = "Sheet1";                    // Target sheet tab name
var BEARER_TOKEN = "";                        // Leave empty if auth is not enabled
var NOTIFY_EMAIL = "";                        // Email for failure alerts (leave empty to skip)
// ====================================

function fetchCSVGetterData() {
  try {
    var options = {};

    // Add auth header if Bearer token is set
    if (BEARER_TOKEN) {
      options = {
        headers: {
          "Authorization": "Bearer " + BEARER_TOKEN
        }
      };
    }

    // Fetch data from CSV Getter
    var response = UrlFetchApp.fetch(ENDPOINT_URL, options);
    var statusCode = response.getResponseCode();

    if (statusCode !== 200) {
      var errorMsg = "CSV Getter returned status " + statusCode + ": " + response.getContentText();
      Logger.log(errorMsg);
      sendFailureAlert(errorMsg);
      return;
    }

    var csvContent = response.getContentText();

    if (!csvContent || csvContent.trim() === "") {
      var emptyMsg = "CSV Getter returned empty data.";
      Logger.log(emptyMsg);
      sendFailureAlert(emptyMsg);
      return;
    }

    // Parse CSV into rows
    var rows = Utilities.parseCsv(csvContent);

    // Get the target sheet
    var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
    var sheet = spreadsheet.getSheetByName(SHEET_NAME);

    if (!sheet) {
      sheet = spreadsheet.insertSheet(SHEET_NAME);
    }

    // Clear existing data and write new data
    sheet.clearContents();
    sheet.getRange(1, 1, rows.length, rows[0].length).setValues(rows);

    Logger.log("Successfully imported " + rows.length + " rows (including header) at " + new Date().toISOString());

  } catch (error) {
    var errMsg = "Error fetching CSV Getter data: " + error.message;
    Logger.log(errMsg);
    sendFailureAlert(errMsg);
  }
}

/**
 * Sends an email alert when the import fails.
 */
function sendFailureAlert(errorMessage) {
  if (!NOTIFY_EMAIL) return;

  try {
    var subject = "CSV Getter Import Failed - " + SpreadsheetApp.getActiveSpreadsheet().getName();
    var body = "The scheduled CSV Getter import failed.\n\n" +
               "Spreadsheet: " + SpreadsheetApp.getActiveSpreadsheet().getUrl() + "\n" +
               "Sheet: " + SHEET_NAME + "\n" +
               "Endpoint: " + ENDPOINT_URL + "\n" +
               "Time: " + new Date().toISOString() + "\n\n" +
               "Error: " + errorMessage + "\n\n" +
               "Please check your endpoint at https://csvgetter.com";

    MailApp.sendEmail(NOTIFY_EMAIL, subject, body);
    Logger.log("Failure alert sent to " + NOTIFY_EMAIL);
  } catch (e) {
    Logger.log("Could not send failure alert email: " + e.message);
  }
}
```

#### Step 3: Configure

1. Replace `YOUR_ENDPOINT_ID` with your actual endpoint ID.
2. Set `SHEET_NAME` to the tab name where data should be written.
3. If your endpoint has auth enabled, set `BEARER_TOKEN` to your token.
4. (Optional) Set `NOTIFY_EMAIL` to receive alerts on failure.

#### Step 4: Test

1. Click the **Run** button (play icon) at the top.
2. The first time, Google will ask you to authorize the script. Click **Review Permissions** > **Allow**.
3. Check your Google Sheet — the data should appear.
4. Check **Execution log** (View > Execution log) for success/error messages.

***

### Setting Up a Time-Driven Trigger

To run the import automatically on a schedule:

#### Option A: Via the Apps Script UI

1. In the Apps Script editor, click the **Triggers** icon (clock icon) in the left sidebar.
2. Click **+ Add Trigger**.
3. Configure:
   * **Function:** `fetchCSVGetterData`
   * **Deployment:** Head
   * **Event source:** Time-driven
   * **Type of time-based trigger:** Choose one:
     * **Minutes timer** — Every 5, 10, 15, or 30 minutes
     * **Hour timer** — Every 1, 2, 4, 6, 8, or 12 hours
     * **Day timer** — Once per day (pick the time window)
     * **Week timer** — Once per week (pick day and time)
4. Click **Save**.

#### Option B: Via Code

Add this function to your script and run it once to create the trigger:

```javascript
/**
 * Creates a time-driven trigger. Run this function ONCE to set up the schedule.
 */
function createDailyTrigger() {
  // Delete any existing triggers for this function to avoid duplicates
  var triggers = ScriptApp.getProjectTriggers();
  for (var i = 0; i < triggers.length; i++) {
    if (triggers[i].getHandlerFunction() === "fetchCSVGetterData") {
      ScriptApp.deleteTrigger(triggers[i]);
    }
  }

  // Create a new daily trigger at 8:00-9:00 AM
  ScriptApp.newTrigger("fetchCSVGetterData")
    .timeBased()
    .everyDays(1)
    .atHour(8)
    .create();

  Logger.log("Daily trigger created.");
}
```

Other schedule options:

```javascript
// Every hour
ScriptApp.newTrigger("fetchCSVGetterData")
  .timeBased()
  .everyHours(1)
  .create();

// Every 30 minutes
ScriptApp.newTrigger("fetchCSVGetterData")
  .timeBased()
  .everyMinutes(30)
  .create();

// Every Monday at 9 AM
ScriptApp.newTrigger("fetchCSVGetterData")
  .timeBased()
  .onWeekDay(ScriptApp.WeekDay.MONDAY)
  .atHour(9)
  .create();
```

***

### Importing JSON Instead of CSV

If you prefer JSON (e.g., for more control over parsing):

```javascript
function fetchCSVGetterDataAsJSON() {
  try {
    var url = ENDPOINT_URL + "?type=json_records";
    var options = {};

    if (BEARER_TOKEN) {
      options = {
        headers: { "Authorization": "Bearer " + BEARER_TOKEN }
      };
    }

    var response = UrlFetchApp.fetch(url, options);

    if (response.getResponseCode() !== 200) {
      sendFailureAlert("Status " + response.getResponseCode() + ": " + response.getContentText());
      return;
    }

    var data = JSON.parse(response.getContentText());

    if (!data || data.length === 0) {
      sendFailureAlert("No data returned.");
      return;
    }

    var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
    if (!sheet) {
      sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(SHEET_NAME);
    }

    // Write headers from first object's keys
    var headers = Object.keys(data[0]);
    sheet.clearContents();
    sheet.getRange(1, 1, 1, headers.length).setValues([headers]);

    // Write data rows
    var rows = data.map(function(record) {
      return headers.map(function(header) {
        var value = record[header];
        return value !== null && value !== undefined ? value : "";
      });
    });

    if (rows.length > 0) {
      sheet.getRange(2, 1, rows.length, headers.length).setValues(rows);
    }

    Logger.log("Imported " + rows.length + " records.");

  } catch (error) {
    sendFailureAlert(error.message);
  }
}
```

***

### Using SQL Filters

Add SQL to the URL to only import filtered data:

```javascript
var ENDPOINT_URL = "https://api.csvgetter.com/YOUR_ENDPOINT_ID?sql=" +
  encodeURIComponent("SELECT name, email, status FROM csvgetter WHERE status = 'Active' ORDER BY name");
```

***

### Credit Usage

Each time the script runs and hits the endpoint, it uses 1 credit. Plan your trigger frequency accordingly:

| Frequency     | Credits/Month |
| ------------- | ------------- |
| Every 30 min  | \~1,440       |
| Every hour    | \~720         |
| Every 6 hours | \~120         |
| Daily         | \~30          |
| Weekly        | \~4           |

***

### Troubleshooting

| Issue                             | Cause                                             | Fix                                         |
| --------------------------------- | ------------------------------------------------- | ------------------------------------------- |
| `Exception: Request failed`       | Endpoint URL is wrong or server is down           | Verify the URL works in a browser first     |
| `401 Unauthorized`                | Bearer token is missing or wrong                  | Check `BEARER_TOKEN` value                  |
| `403 Forbidden`                   | Out of credits                                    | Purchase credits at csvgetter.com           |
| `Exceeded maximum execution time` | Dataset too large for Apps Script timeout (6 min) | Add `sql=...LIMIT 5000` to reduce data size |
| Script runs but sheet is empty    | Wrong `SHEET_NAME`                                | Check the tab name matches exactly          |
| Trigger not firing                | Trigger wasn't saved or was deleted               | Re-create the trigger in the Triggers panel |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.csvgetter.com/google-apps-script-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
