Tidemark listens to history.pushState and popstate, so route changes in most single-page apps are counted as pageviews with no extra code. Navigating to the path you are already on doesn’t send a second pageview.
history.pushState
popstate
If your router uses #/path, use the hash variant:
#/path
hash
<script defer data-domain="example.com" src="https://stats.example.com/js/script.hash.js"></script>
The fragment is then stored as part of the page path.
If your app updates the URL before the page is ready, use the manual variant and send the pageview yourself:
manual
router.afterEach(() => plausible('pageview'))