Best practice (especially) for SPA sites is to work with the site developers to implement an event driven data layer.
Take a look at window.appEventData on https://orbitalprovisions.searchdiscovery.com/collections/frontpage/products/lego-women-of-nasa as an example.
In this example, there are four events that are pushed tho the EDDL:
Page Load Started (provides the page object).
User Detected (provides the user object)
Product Viewed (provides the product object (array).
Page Load Completed - provides no data but is used to trigger the s.t()
As each of first three events are pushed, Launch rules are triggered which set variables on the s object.
The push of Page Load Completed sends the beacon, and runs the clear vars action.