Answering my own question in case anyone else runs into this issue.
So it looks like to make this work you have to track which group is currently expanded and ONLY collapse that particular group. CollapseAllGroups doesn't seem to do anything and iterating through every group collapsing it (whether it's expanded or not and whether it's the group to-be-expanded or not) produces...unexpected results.
To accomplish this, I added an activeGroup JavaScript variable which I initialize to -1. After expanding the first group in the client-side GridCreated event, I reinitialize the activeGroup variable to 0. In the client-side GroupExpanding event, I check whether (activeGroup >= 0) and, if so, collapse that group (this is why the activeGroup variable is first initialized to -1. Otherwise, the GridCreated group expansion will try to collapse a group that isn't expanded and will cause unexpected behaviors.) Finally, using jQuery, I attach an additional 'click' event handler to the expand/collapse buttons to update activeGroup to the correct group index.