Zurich hit back for a point
It looked grim for Urs Fischer's table-toppers when Brice Owona gave the hosts a second-minute lead and Silvan Aegerter was dismissed after just 14 minutes.
Substitute Adrian Nikci levelled nine minutes from time, but that short period was to require a further comeback as Philipp Muntwiler restored St Gallen's lead in the 87th minute.
Dusan Djuric did the honours in the last minute to keep Zurich top on goal difference from Basel, who beat Bellinzona 2-0.
Benjamin Huggel set the second-placed side on their way in the 39th minute and Alexander Frei added a late second.