Real-time text extraction from Google Docs using Chrome extension content script

I’m working on a Chrome extension that needs to get all text from a Google Docs document as users type, edit, or make changes. The problem is Google Docs doesn’t use regular text input fields, so normal methods don’t work.

What I’ve tried so far:

  1. Input event listeners - Doesn’t work with Google Docs structure
  2. Keydown events - Can’t track cursor position or paste operations properly
  3. Monitoring doc-appview elements - Not detecting changes

My code finds the container but the MutationObserver never triggers. What am I missing here?

Current approach:

function initializeDocsTextCapture() {
  if (window.location.hostname !== 'docs.google.com') return;
  console.log('🟢 Extension loaded on', window.location.href);

  function attachTextWatcher() {
    const docContainer = document.querySelector('.doc-appview');
    if (!docContainer) {
      setTimeout(attachTextWatcher, 300);
      console.log('Searching for .doc-appview...');
      return;
    }

    console.log('Container found, initializing watcher...');
    let previousContent = '';

    const textObserver = new MutationObserver(() => {
      console.log('Change detected');
      const textLines = Array.from(document.querySelectorAll('.doc-lineview'));
      const documentText = textLines.map(element => element.innerText).join('\n').trim();
      if (documentText !== previousContent) {
        previousContent = documentText;
        console.log('Text changed, updating storage');
        chrome.runtime.sendMessage({
          action: 'text_update',
          content: documentText
        });
      }
    });

    textObserver.observe(docContainer, {
      childList: true,
      subtree: true,
      characterData: true
    });

    console.log('📝 Text monitoring active');
  }

  attachTextWatcher();
}

window.addEventListener('load', initializeDocsTextCapture);

The observer setup looks correct but changes aren’t being detected. Any suggestions for a better approach or what I’m doing wrong?

Google Docs constantly creates and destroys DOM elements, so MutationObserver often misses changes or fires randomly. You’re probably watching the wrong part of the DOM. Don’t observe .doc-appview - target .kix-appview-editor instead since that’s where the actual editing happens. Google Docs renders text through canvas and virtual DOM updates, which breaks most text extraction methods. Try document.getSelection() to grab what users have selected or are currently typing, and poll the document structure periodically. I’ve had better luck listening for the selectionchange event on the document - it fires when users move their cursor or select text. Way more reliable than trying to catch DOM mutations.

Had the same issue with a Docs extension last year. The timing’s off - Google Docs loads content dynamically, so your observer attaches before the text containers are ready. Don’t wait just 300ms. Use a longer interval or specifically check for .kix-lineview elements since that’s where the actual text lives. Also, debounce your text extraction because Docs fires tons of mutation events when you’re typing. I ended up using setInterval every 500ms instead of relying on MutationObserver for real-time changes - worked way better.

try targeting document.body instead of .doc-appview for your observer. google docs updates happen higher up in the dom, so you’re probably being too specific with that selector. also throw attributes: true into your observer config - docs changes element attributes when you edit stuff.