diff --git a/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/README.md b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/README.md
new file mode 100644
index 000000000000..d7330f233425
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/README.md
@@ -0,0 +1,9 @@
+Tests in this suite are meant to test the lifetime of a trace in the browser SDK and how different events sent are
+connected to a trace. This suite distinguishes the following cases:
+
+1. `pageload` - Traces started on the initial pageload as head of trace
+2. `pageload-meta` - Traces started on the initial pageload as a continuation of the trace on the server (via ` `
+ tags)
+3. `navigation` - Traces started during navigations on a page
+
+Tests scenarios should be fairly similar for all three cases but it's important we test all of them.
diff --git a/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/template.html b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/template.html
new file mode 100644
index 000000000000..61372c8605e5
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/template.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+ Throw Error
+ Fetch Request
+
+
diff --git a/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/test.ts b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/test.ts
new file mode 100644
index 000000000000..2f872b398d87
--- /dev/null
+++ b/dev-packages/browser-integration-tests/suites/tracing/trace-lifetime/pageload-meta/test.ts
@@ -0,0 +1,159 @@
+import { expect } from '@playwright/test';
+import type { Event } from '@sentry/types';
+import { sentryTest } from '../../../../utils/fixtures';
+import {
+ getFirstSentryEnvelopeRequest,
+ getMultipleSentryEnvelopeRequests,
+ shouldSkipTracingTest,
+} from '../../../../utils/helpers';
+
+const META_TAG_TRACE_ID = '12345678901234567890123456789012';
+const META_TAG_PARENT_SPAN_ID = '1234567890123456';
+const META_TAG_BAGGAGE =
+ 'sentry-trace_id=12345678901234567890123456789012,sentry-sample_rate=0.2,sentry-transaction=my-transaction,sentry-public_key=public,sentry-release=1.0.0,sentry-environment=prod';
+
+sentryTest(
+ 'create a new trace for a navigation after the tag pageload trace',
+ async ({ getLocalTestPath, page }) => {
+ if (shouldSkipTracingTest()) {
+ sentryTest.skip();
+ }
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const pageloadEvent = await getFirstSentryEnvelopeRequest(page, url);
+ const navigationEvent = await getFirstSentryEnvelopeRequest(page, `${url}#foo`);
+
+ const pageloadTraceContext = pageloadEvent.contexts?.trace;
+ const navigationTraceContext = navigationEvent.contexts?.trace;
+
+ expect(pageloadTraceContext).toMatchObject({
+ op: 'pageload',
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+ expect(navigationTraceContext).toMatchObject({
+ op: 'navigation',
+ trace_id: expect.stringMatching(/^[0-9a-f]{32}$/),
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+ // navigation span is head of trace, so there's no parent span:
+ expect(navigationTraceContext?.trace_id).not.toHaveProperty('parent_span_id');
+
+ expect(pageloadTraceContext?.trace_id).not.toEqual(navigationTraceContext?.trace_id);
+ },
+);
+
+sentryTest('error after tag pageload has pageload traceId', async ({ getLocalTestPath, page }) => {
+ if (shouldSkipTracingTest()) {
+ sentryTest.skip();
+ }
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const pageloadEvent = await getFirstSentryEnvelopeRequest(page, url);
+ expect(pageloadEvent.contexts?.trace).toMatchObject({
+ op: 'pageload',
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+
+ const errorEventPromise = getFirstSentryEnvelopeRequest(page);
+ await page.locator('#errorBtn').click();
+ const errorEvent = await errorEventPromise;
+
+ expect(errorEvent.contexts?.trace).toMatchObject({
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+});
+
+sentryTest('error during tag pageload has pageload traceId', async ({ getLocalTestPath, page }) => {
+ if (shouldSkipTracingTest()) {
+ sentryTest.skip();
+ }
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const envelopeRequestsPromise = getMultipleSentryEnvelopeRequests(page, 2);
+ await page.goto(url);
+ await page.locator('#errorBtn').click();
+ const events = await envelopeRequestsPromise;
+
+ const pageloadEvent = events.find(event => event.type === 'transaction');
+ const errorEvent = events.find(event => !event.type);
+
+ expect(pageloadEvent?.contexts?.trace).toMatchObject({
+ op: 'pageload',
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+
+ expect(errorEvent?.contexts?.trace).toMatchObject({
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+});
+
+sentryTest(
+ 'outgoing fetch request after tag pageload has pageload traceId in headers',
+ async ({ getLocalTestPath, page }) => {
+ if (shouldSkipTracingTest()) {
+ sentryTest.skip();
+ }
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const pageloadEvent = await getFirstSentryEnvelopeRequest(page, url);
+ expect(pageloadEvent?.contexts?.trace).toMatchObject({
+ op: 'pageload',
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+
+ const requestPromise = page.waitForRequest('http://example.com/*');
+ await page.locator('#fetchBtn').click();
+ const request = await requestPromise;
+ const headers = request.headers();
+
+ // sampling decision is propagated from meta tag's sentry-trace sampled flag
+ expect(headers['sentry-trace']).toMatch(new RegExp(`^${META_TAG_TRACE_ID}-[0-9a-f]{16}-1$`));
+ expect(headers['baggage']).toBe(META_TAG_BAGGAGE);
+ },
+);
+
+sentryTest(
+ 'outgoing fetch request during tag pageload has pageload traceId in headers',
+ async ({ getLocalTestPath, page }) => {
+ if (shouldSkipTracingTest()) {
+ sentryTest.skip();
+ }
+
+ const url = await getLocalTestPath({ testDir: __dirname });
+
+ const pageloadEventPromise = getFirstSentryEnvelopeRequest(page);
+ const requestPromise = page.waitForRequest('http://example.com/*');
+ await page.goto(url);
+ await page.locator('#fetchBtn').click();
+ const [pageloadEvent, request] = await Promise.all([pageloadEventPromise, requestPromise]);
+
+ expect(pageloadEvent?.contexts?.trace).toMatchObject({
+ op: 'pageload',
+ trace_id: META_TAG_TRACE_ID,
+ parent_span_id: META_TAG_PARENT_SPAN_ID,
+ span_id: expect.stringMatching(/^[0-9a-f]{16}$/),
+ });
+
+ const headers = request.headers();
+
+ // sampling decision is propagated from meta tag's sentry-trace sampled flag
+ expect(headers['sentry-trace']).toMatch(new RegExp(`^${META_TAG_TRACE_ID}-[0-9a-f]{16}-1$`));
+ expect(headers['baggage']).toBe(META_TAG_BAGGAGE);
+ },
+);