Chrome Extension Extension Onboarding — Best Practices

6 min read

Extension Onboarding Patterns

User onboarding is critical for Chrome extensions to ensure users understand and adopt key features. This document covers proven onboarding patterns that improve user engagement and reduce early churn.

First Install Detection

Use chrome.runtime.onInstalled to detect first-time installation:

chrome.runtime.onInstalled.addListener((details) => {
  if (details.reason === 'install') {
    // First-time install - start onboarding
    chrome.storage.local.set({ onboardingCompleted: false });
    openOnboardingPage();
  } else if (details.reason === 'update') {
    // Extension updated - show what's new
    handleUpdate(details.previousVersion);
  }
});

function openOnboardingPage() {
  chrome.tabs.create({ url: 'onboarding.html' });
}

Welcome Page

Open an onboarding tab immediately after first install. The welcome page should:

// In onboarding.html
document.getElementById('getStarted').addEventListener('click', () => {
  startSetupWizard();
});

Step-by-Step Setup Wizard

Guide users through key features with a multi-step wizard:

  1. Introduction - What the extension does
  2. Permissions - Explain and request necessary permissions
  3. Configuration - Set initial preferences
  4. Tutorial - Quick walkthrough of main features
  5. Completion - Confirmation and tips

Permission Requests During Onboarding

Always explain why each permission is needed before requesting:

const permissionRationale = {
  'tabs': 'We need access to tabs to help you manage your workflow',
  'storage': 'Storage permission saves your preferences across sessions',
  'activeTab': 'ActiveTab lets us assist with the current page you're viewing'
};

function requestPermissionWithExplanation(permission, rationale) {
  showExplanationModal(permission, rationale);
  // Then request the actual permission
  chrome.permissions.request({ permissions: [permission] });
}

Feature Highlights & Tooltips

Use tooltip-style overlays to highlight new features:

function showFeatureTour(steps) {
  let currentStep = 0;
  
  function nextStep() {
    if (currentStep >= steps.length) {
      endTour();
      return;
    }
    const step = steps[currentStep];
    highlightElement(step.selector, step.message);
    currentStep++;
  }
  
  return { nextStep, endTour };
}

Interactive Tutorials

In-extension guided tours help users learn by doing:

Settings Initialization

Set sensible defaults, then allow customization:

const defaultSettings = {
  theme: 'light',
  notifications: true,
  autoSave: true,
  shortcut: 'Ctrl+Shift+E'
};

function initializeSettings() {
  chrome.storage.sync.get(defaultSettings, (result) => {
    if (chrome.runtime.lastError) {
      // First run - set defaults
      chrome.storage.sync.set(defaultSettings);
    }
  });
}

Pin Extension Prompt

Remind users to pin the extension for easy access:

function showPinPrompt() {
  // Check if already pinned
  chrome.action.isPinned((isPinned) => {
    if (!isPinned) {
      showModal('Pin Extension', 
        'For the best experience, pin this extension to your toolbar.');
    }
  });
}

Keyboard Shortcut Setup

Display current shortcuts and link to shortcut settings:

function displayShortcuts() {
  chrome.commands.getAll((commands) => {
    const shortcuts = commands.map(cmd => 
      `${cmd.name}: ${cmd.shortcut || 'Not set'}`
    );
    renderShortcutList(shortcuts);
  });
}

// Link to chrome://extensions/shortcuts
document.getElementById('shortcutSettings').href = 
  'chrome://extensions/shortcuts';

Skip Option

Always allow users to skip onboarding:

function skipOnboarding() {
  chrome.storage.local.set({ 
    onboardingCompleted: true,
    skippedAt: Date.now()
  });
  redirectToMainPage();
}

Progress Tracking

Store completion status in storage:

function completeOnboarding() {
  chrome.storage.local.set({
    onboardingCompleted: true,
    onboardingCompletedAt: Date.now(),
    onboardingVersion: chrome.runtime.getManifest().version
  });
}

function checkOnboardingStatus(callback) {
  chrome.storage.local.get('onboardingCompleted', (result) => {
    callback(result.onboardingCompleted);
  });
}

Returning User Detection

Distinguish between new installs and updates:

chrome.runtime.onInstalled.addListener((details) => {
  switch (details.reason) {
    case 'install':
      showNewUserOnboarding();
      break;
    case 'update':
      showWhatsNew(details.previousVersion);
      break;
    case 'chrome_update':
      // Handle browser update
      break;
  }
});

A/B Testing Onboarding Flows

Test different onboarding approaches:

function assignOnboardingVariant() {
  const variants = ['wizard', 'video', 'interactive'];
  const variant = variants[Math.floor(Math.random() * variants.length)];
  chrome.storage.local.set({ onboardingVariant: variant });
  return variant;
}

Part of the Chrome Extension Guide by theluckystrike. Built at zovo.one.