googleworkspace / googleworkspace/apps-script-samples

Google Sheets: Add WebSocket Support for Real-Time Communication Between Code.gs and Client-Side HTML

Open
#557 0 comments 5 reactions 1 assignee View on GitHub

@vinay-google is already working on this.

Since Aug 28, 2025.

Dominant language
JavaScript
Stars
5.2k
Forks
2k
PR merge metrics
No merged PRs in 30d

Description

Problem Description

Google Apps Script currently lacks support for persistent, bidirectional communication between server-side Code.gs and client-side HTML served via HtmlService. This forces developers to use inefficient polling mechanisms to achieve pseudo-real-time updates.

Current Limitations
  • google.script.run only supports one-way RPC calls from client to server
  • No WebSocket or Server-Sent Events (SSE) support
  • Polling with setInterval creates unnecessary server load and latency
  • 6-minute execution limit prevents long-running server processes
Use Cases Impacted
  1. Real-time collaboration tools - Displaying live cursor positions or selection changes
  2. Dashboard applications - Live data updates without page refresh
  3. Progress indicators - Streaming progress of long-running operations
  4. Chat/notification systems - Instant message delivery within Sheets add-ons
Proposed Solution

Implement WebSocket support in Google Apps Script with the following API:

// Code.gs - Server-side
function onWebSocketConnection(ws) {
  // Handle new WebSocket connection
  ws.on('message', (data) => {
    // Process incoming message
    const parsed = JSON.parse(data);
    
    if (parsed.type === 'subscribe') {
      // Set up sheet listeners
      const listener = SpreadsheetApp.onSelectionChange((e) => {
        ws.send(JSON.stringify({
          type: 'selectionUpdate',
          range: e.range.getA1Notation(),
          sheet: e.range.getSheet().getName(),
          timestamp: new Date().getTime()
        }));
      });
      
      ws.on('close', () => {
        listener.remove(); // Clean up
      });
    }
  });
  
  ws.on('error', (error) => {
    console.error('WebSocket error:', error);
  });
}

// Alternative: SSE for one-way streaming
function* onServerSentEvent() {
  const cache = CacheService.getUserCache();
  while (true) {
    const data = cache.get('latestUpdate');
    if (data) {
      yield data;
      cache.remove('latestUpdate');
    }
    Utilities.sleep(100); // Non-blocking in actual implementation
  }
}
// index.html - Client-side
<script>
  // WebSocket approach
  const ws = google.script.websocket.connect();
  
  ws.onopen = () => {
    ws.send(JSON.stringify({ type: 'subscribe' }));
  };
  
  ws.onmessage = (event) => {
    const data = JSON.parse(event.data);
    updateDisplay(data);
  };
  
  // Alternative: EventSource for SSE
  const eventSource = google.script.eventSource.connect();
  
  eventSource.onmessage = (event) => {
    const data = JSON.parse(event.data);
    updateDisplay(data);
  };
</script>
Benefits
  1. Reduced server load - Eliminate constant polling requests
  2. Lower latency - Instant updates instead of polling intervals
  3. Better UX - True real-time features in Sheets add-ons
  4. Resource efficiency - Maintain single connection vs repeated HTTP calls
  5. Cleaner code - Event-driven instead of interval-based patterns
Backward Compatibility
  • Keep existing google.script.run API unchanged
  • WebSocket/SSE features would be opt-in via new APIs
  • Graceful fallback to polling if WebSocket unavailable
Security Considerations
  • Maintain same OAuth scopes and permissions model
  • WebSocket connections authenticated via existing session
  • Rate limiting to prevent abuse
  • Automatic timeout after inactivity period

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.