John McGinn headed the visitors in front shortly before the break and Paul McGowan's second-half strike sent his side up to 10th place in the table.
The hosts quickly showed their attacking threat when Danny Wilson's header was tipped over by Christopher Dillo, but St Mirren also made a lively start and Kenny McLean fired wide from outside the box.
Steven Thompson sent two shots wide of the target as the Buddies continued to threaten and their attacking efforts were rewarded when McGinn (42) headed in from close range after he was picked out by Conor Newton.
Hearts tried to find a leveller after the break as Jamie Walker tested Dilo, but they slipped further behind in the 57th minute when McGowan stabbed in the loose ball after Jamie MacDonald fumbled.
Wilson should have hauled Hearts back into the game but he headed wide of the target, while Thompson nearly added a late third with a shot that flew past the post.