// Slides · Apps Script

Sort slides alphabetically by title in Google Slides.

Reorder Google Slides by title text using Apps Script. Covers the index-shift trap in Slide.move() and the correct pattern: sort handles in memory, then move in ascending order.

I have a deck with dozens of slides and I need them in alphabetical order by title without dragging them one by one.

The script

copy · paste · trigger
sortSlidesAlpha.gs
Apps Script
// Sort all slides in the active presentation alphabetically by title shape text.
// Run from Extensions > Apps Script > Run.
function sortSlidesAlphabetically() {
  var pres = SlidesApp.getActivePresentation();
  var slides = pres.getSlides();

  // Build a list of { slide, title } pairs while indexes are stable.
  var pairs = slides.map(function(slide) {
    var shapes = slide.getPageElements();
    var title = '';
    for (var i = 0; i < shapes.length; i++) {
      var el = shapes[i];
      if (el.getPageElementType() === SlidesApp.PageElementType.SHAPE) {
        title = el.asShape().getText().asString();
        break;
      }
    }
    return { slide: slide, title: title.trim().toLowerCase() };
  });

  // Sort the pairs in memory — no moves yet.
  pairs.sort(function(a, b) {
    return a.title < b.title ? -1 : a.title > b.title ? 1 : 0;
  });

  // Move each slide to its target index in ascending order.
  // Because we move 0, 1, 2... every earlier position is already settled.
  for (var j = 0; j < pairs.length; j++) {
    pairs[j].slide.move(j);
  }
}

Need a variant? Gnaw writes a custom version from one sentence — fields, triggers, edge cases handled.

Walkthrough

Why naive swap loops destroy your deck

The first time I tried sorting slides I wrote a double loop that swapped adjacent slides in place, the same way you would swap array elements. It produced a scrambled deck every time. The reason is that Slide.move(index) is not a swap — it shifts the positions of every slide that comes after the moved one. By the time you issue the second move(), the indexes you computed in the first pass are wrong.

The fix is to never compute a 'current index' mid-sort. Pull all the slide objects into a plain JavaScript array alongside their title text, sort that array in memory, and only then start issuing move() calls. At that point the slide objects themselves are your handles — stable references that survive any re-ordering of the deck.

Reading the title from a slide's first shape

Google Slides does not expose a dedicated 'title' property the way Sheets exposes cell values. A slide's title is just the text of whichever shape occupies the title placeholder, and that shape is typically the first SHAPE element returned by getPageElements(). The code above iterates page elements, finds the first one whose type is SHAPE, calls asShape().getText().asString(), and stops there.

Two caveats worth knowing: if a slide has no text shapes at all (an image-only slide, for example) the title resolves to an empty string, so blank-titled slides will sort to the top. If your deck uses a layout where the subtitle comes before the title in DOM order, you may need to change the break condition — inspect shapes[0] vs shapes[1] in Logger.log() to confirm which is which before running the sort on a real deck.

The sort itself uses .toLowerCase() on both sides so 'Zebra' does not land after 'apple'. That normalization only affects sort order; it does not touch the actual slide text.

Moving in ascending order to keep positions settled

The loop calls pairs[j].slide.move(j) for j = 0, 1, 2, and so on. Moving a slide to position 0 pushes everything else one step right, which would break subsequent moves — except that we move in ascending order, so by the time we issue move(1), the slide at position 0 is already correct and will not be touched again. Each move() only disturbs positions equal to or greater than the target, and those are exactly the positions we have not yet settled.

This is the same insight behind insertion sort: work left-to-right and every earlier position stays fixed. The total number of API calls equals the number of slides, which keeps quota usage minimal even on large decks. Google Apps Script's daily quota for Slides operations is 1,000 per user per day on the free tier and 10,000 on Workspace, so a 50-slide sort costs 50 calls — well inside either limit.

Want a custom version?

Describe your sheet and the rule you want. Gnaw writes the Apps Script — fields, triggers, edge cases — in one shot.

FAQ

4 questions
What happens to slides that have no title text?
They resolve to an empty string and sort to the top of the deck because an empty string is lexicographically less than any letter. If you want them at the bottom, change the sort comparator to return a.title === '' ? 1 : b.title === '' ? -1 : (compare normally).
Can I sort by the slide number shown in the thumbnail panel instead of the title?
Slide.getObjectId() returns a stable ID string, not a human-readable number. The display number is just the slide's current position in getSlides(), so sorting by it is a no-op. If you want a numeric sort on some embedded number in the title text, parse it out with parseInt() before the comparison.
Does this work on a shared deck where I only have commenter access?
No. Slide.move() requires editor access. The script will throw an exception at the first move() call if the account running it only has view or comment rights. You need to be an editor on the file, or the file owner needs to run the script themselves.
How do I undo the sort if I run it by mistake?
Apps Script does not integrate with the Slides undo stack, so Ctrl+Z will not reverse it. Make a copy of the presentation before running the script (File > Make a copy), or use Revision history (File > Version history > See version history) to restore the pre-run state.