Repository: PostHog/posthog-js
Pull request #1924: fix: prevent survey events to affect multiple surveys
Author: login: lucasheriques
Labels: name: feature/surveys
Created: 2025-04-27T17:08:53Z | Merged: 2025-04-29T14:10:54Z

## Changes

There's a bug right now that, if a survey sent/dismissed event is sent, it closes any other surveys that might be visible.

While we only support one popup survey being shown, for feedback surveys there's no such restriction.

So this PR changes the event emitters for PHSurveySent and PHSurveyClosed to also check for the survey id to only close the survey in the event context. This is tested using a e2e test.

There's also another change, in preparation for a bigger one: it changes the survey class container name from being `PostHogWidget${surveyId}` or `PostHogSurvey${surveyId}` depending on the type to be a unified `PostHogSurvey-${surveyId}`.

This is needed to have constant class names between surveys no matter the type. There's no functional changes. But it does require updating most of our e2e tests to the new value.

## Checklist
- [x] Tests for new code (see [advice on the tests we use](https://github.com/PostHog/posthog-js#tiers-of-testing))
- [x] Accounted for the impact of any changes across different browsers
- [x] Accounted for backwards compatibility of any changes (no breaking changes in posthog-js!)
- [x] Took care not to unnecessarily increase the bundle size




Diff:
diff --git a/package.json b/package.json
index a83070efc5..4bc8cbcf48 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,8 @@
         "playwright": "pnpm exec playwright test --project webkit --project firefox --project chromium",
         "playwright-ui": "pnpm exec playwright test --ui --project webkit --project firefox --project chromium",
         "playwright-webserver": "npx http-server ./ -p 8082",
+        "playwright:surveys": "pnpm exec playwright test playwright/surveys/* --project webkit --project firefox --project chromium",
+        "playwright:surveys:ui": "pnpm exec playwright test playwright/surveys/* --ui --project webkit --project firefox --project chromium",
         "prepare": "[ -z \"$VERCEL\" ] && husky install || echo \"Skipping husky install on vercel build\"",
         "deprecate-old-versions": "node scripts/deprecate-old-versions.mjs",
         "check-testcafe-results": "ts-node testcafe/check-testcafe-results.js",
diff --git a/playwright/surveys/core-display-logic.spec.ts b/playwright/surveys/core-display-logic.spec.ts
index b9debf7172..1ea71b2ffa 100644
--- a/playwright/surveys/core-display-logic.spec.ts
+++ b/playwright/surveys/core-display-logic.spec.ts
@@ -38,14 +38,14 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         await page.reload()
 
         await start({ ...startOptions, type: 'reload' }, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
     })
 
     test('does not show the same survey to user if they have dismissed it before', async ({ page, context }) => {
@@ -69,9 +69,9 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey123').locator('.cancel-btn-wrapper').click()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).not.toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.cancel-btn-wrapper').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeInViewport()
 
         expect(
             await page.evaluate(() => {
@@ -84,7 +84,7 @@ test.describe('surveys - core display logic', () => {
         await start({ ...startOptions, type: 'reload' }, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).not.toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeInViewport()
     })
 
     test('does not show the same survey to user if they responded to it before', async ({ page, context }) => {
@@ -108,9 +108,9 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey123').locator('textarea').type('some feedback')
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('textarea').type('some feedback')
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
 
         expect(
             await page.evaluate(() => {
@@ -118,14 +118,14 @@ test.describe('surveys - core display logic', () => {
             })
         ).toBeTruthy()
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).not.toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeInViewport()
 
         await page.reload()
 
         await start({ ...startOptions, type: 'reload' }, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).not.toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeInViewport()
 
         expect(
             await page.evaluate(() => {
@@ -159,7 +159,7 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         const lastSeenDate = await page.evaluate(() => {
             return window.localStorage.getItem('lastSeenSurveyDate')
@@ -172,7 +172,7 @@ test.describe('surveys - core display logic', () => {
         await start({ ...startOptions, type: 'reload' }, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).not.toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeInViewport()
     })
 
     test('does not allow user to submit non optional survey questions if they have not responded to it', async ({
@@ -200,9 +200,9 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.form-submit')).toHaveAttribute('disabled')
-        await page.locator('.PostHogSurvey123').locator('textarea').type('some feedback')
-        await expect(page.locator('.PostHogSurvey123').locator('.form-submit')).not.toHaveAttribute('disabled')
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.form-submit')).toHaveAttribute('disabled')
+        await page.locator('.PostHogSurvey-123').locator('textarea').type('some feedback')
+        await expect(page.locator('.PostHogSurvey-123').locator('.form-submit')).not.toHaveAttribute('disabled')
     })
 })
diff --git a/playwright/surveys/customization.spec.ts b/playwright/surveys/customization.spec.ts
index 44867dbd3c..ea9c28fb73 100644
--- a/playwright/surveys/customization.spec.ts
+++ b/playwright/surveys/customization.spec.ts
@@ -77,22 +77,25 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'What feedback do you have for us?'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             'plain text description'
         )
 
-        await expect(page.locator('.PostHogSurvey123').locator('.footer-branding')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.footer-branding')).toBeVisible()
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveCSS('background-color', black)
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveCSS('color', white)
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveCSS(
+            'background-color',
+            black
+        )
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveCSS('color', white)
 
-        await page.locator('.PostHogSurvey123').locator('textarea').type('This is great!')
+        await page.locator('.PostHogSurvey-123').locator('textarea').type('This is great!')
 
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
     })
@@ -118,8 +121,8 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.footer-branding')).not.toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.footer-branding')).not.toBeVisible()
     })
 
     test('allows html customization for question and thank you element description', async ({ page, context }) => {
@@ -142,11 +145,11 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'Book an interview with us'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description h2')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description h2')).toHaveText(
             'html description'
         )
     })
@@ -174,11 +177,11 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'Book an interview with us'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description h2')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description h2')).toHaveText(
             'html description'
         )
     })
@@ -208,16 +211,16 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'What feedback do you have for us?'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             'plain text description'
         )
-        await page.locator('.PostHogSurvey123').locator('textarea').type('This is great!')
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogSurvey123').locator('.thank-you-message-body h3')).toHaveText(
+        await page.locator('.PostHogSurvey-123').locator('textarea').type('This is great!')
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-body h3')).toHaveText(
             'html thank you message!'
         )
         await pollUntilEventCaptured(page, 'survey sent')
@@ -246,17 +249,17 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'Book an interview with us'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description')).toHaveText(
-            // the escaped html is the content
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description h2')).toHaveCount(0)
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             '<h2>html description</h2>'
         )
     })
 
-    test('does not render html customization for thank you message body if the appearance.thankYouMessageDescriptionContentType does not permit it', async ({
+    test('does not render html customization for thank you message body if the question.thankYouMessageDescriptionContentType does not permit it', async ({
         page,
         context,
     }) => {
@@ -284,11 +287,17 @@ test.describe('surveys - customization', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey123').locator('textarea').type('This is great!')
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogSurvey123').locator('.thank-you-message-body')).toHaveText(
-            // the escaped html is the content
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
+            'What feedback do you have for us?'
+        )
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
+            'plain text description'
+        )
+        await page.locator('.PostHogSurvey-123').locator('textarea').type('This is great!')
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-body h3')).toHaveCount(0)
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-body')).toHaveText(
             '<h3>html thank you message!</h3>'
         )
         await pollUntilEventCaptured(page, 'survey sent')
diff --git a/playwright/surveys/feedback-widget.spec.ts b/playwright/surveys/feedback-widget.spec.ts
index ed74c2ee18..dbb60cc0ce 100644
--- a/playwright/surveys/feedback-widget.spec.ts
+++ b/playwright/surveys/feedback-widget.spec.ts
@@ -77,16 +77,16 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).not.toBeVisible()
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-question')).toHaveText('Feedback for us?')
-        await expect(page.locator('.PostHogWidget123').locator('.survey-question-description')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText('Feedback for us?')
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             'tab feedback widget'
         )
 
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('hello posthog!')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('hello posthog!')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
         await pollUntilEventCaptured(page, 'survey sent')
     })
 
@@ -119,10 +119,10 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
         await page.setViewportSize({ width: 375, height: 667 })
 
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeInViewport()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeInViewport()
     })
 
     test('widgetType is custom selector', async ({ page, context }) => {
@@ -159,18 +159,18 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).not.toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).not.toBeVisible()
         await page.locator('.test-surveys').click()
 
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible({ timeout: 8000 })
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible({ timeout: 8000 })
 
-        await expect(page.locator('.PostHogWidget123').locator('.survey-question')).toHaveText('Feedback for us?')
-        await expect(page.locator('.PostHogWidget123').locator('.survey-question-description')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText('Feedback for us?')
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             'custom selector widget'
         )
 
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('hello posthog!')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('hello posthog!')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
         await pollUntilEventCaptured(page, 'survey sent')
     })
 
@@ -199,15 +199,15 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
-        await page.locator('.PostHogWidget123').locator('#surveyQuestion0Choice1').click()
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('#surveyQuestion0Choice1').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
-        await page.locator('.PostHogWidget123 textarea').first().type('Because I want to learn more about posthog')
-        await page.locator('.PostHogWidget123 .form-submit').click()
-        await page.locator('.PostHogWidget123 .form-submit').click()
+        await page.locator('.PostHogSurvey-123 textarea').first().type('Because I want to learn more about posthog')
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey shown')
         await pollUntilEventCaptured(page, 'survey sent')
@@ -238,10 +238,10 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toBeVisible()
 
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toHaveCSS('color', black)
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toHaveCSS(
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toHaveCSS('color', black)
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toHaveCSS(
             'background-color',
             white
         )
@@ -262,6 +262,7 @@ test.describe('surveys - feedback widget', () => {
                                 widgetLabel: 'Feedback',
                                 widgetType: 'tab',
                                 displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
                             },
                             conditions: {
                                 url: null,
@@ -279,41 +280,161 @@ test.describe('surveys - feedback widget', () => {
         await surveysAPICall
 
         // 1. Check that the survey widget is rendered
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toBeVisible()
 
         // 2. Open the survey
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // 3. Answer the survey
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('first submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // 4. Check for thank you message
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toHaveText('Thank you!')
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toHaveText('Thank you!')
 
         // Verify the event was sent
         await pollUntilEventCaptured(page, 'survey sent')
 
         // 5. Close the thank you message and click the survey tab again
-        await page.locator('.PostHogWidget123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).not.toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
 
         // Open the survey again
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
 
         // 6. Verify survey is rendered again
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // Submit again with different text
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('second submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('second submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // Verify thank you message appears again
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
 
         // Verify second event was sent
         await pollUntilEventCaptured(page, 'survey sent')
     })
+
+    test('if multiple surveys being shown, sending one of them does not close the other one', async ({
+        page,
+        context,
+    }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // fill in first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
+
+        await pollUntilEventCaptured(page, 'survey sent')
+
+        // click on the first survey confirmation message
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+    })
+
+    test('if multiple surveys being shown, closing one does not close the other', async ({ page, context }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // close first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-cancel').click()
+
+        await pollUntilEventCaptured(page, 'survey dismissed')
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+    })
 })
diff --git a/playwright/surveys/question-types.spec.ts b/playwright/surveys/question-types.spec.ts
index 8a10de3d6d..763a328f7c 100644
--- a/playwright/surveys/question-types.spec.ts
+++ b/playwright/surveys/question-types.spec.ts
@@ -66,15 +66,15 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question')).toHaveText(
             'What feedback do you have for us?'
         )
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-question-description')).toHaveText(
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-question-description')).toHaveText(
             'plain text description'
         )
-        await page.locator('.PostHogSurvey123').locator('.survey-form').locator('textarea').type('Great job!')
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').type('Great job!')
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
     })
@@ -100,18 +100,18 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123').locator('.survey-form')).toBeVisible()
-        await expect(page.locator('.PostHogSurvey123').locator('.ratings-number')).toHaveCount(11)
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ratings-number')).toHaveCount(11)
         let i = 0
-        for (const rating of await page.locator('.PostHogSurvey123').locator('.ratings-number').all()) {
+        for (const rating of await page.locator('.PostHogSurvey-123').locator('.ratings-number').all()) {
             await expect(rating).toBeVisible()
             await expect(rating).toHaveText(`${i++}`)
         }
 
-        await page.locator('.PostHogSurvey123').locator('.ratings-number').first().click()
-        await page.locator('.PostHogSurvey123').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.ratings-number').first().click()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
 
-        await expect(page.locator('.PostHogSurvey123').locator('.ratings-number').first()).toHaveText('1')
+        await expect(page.locator('.PostHogSurvey-123').locator('.ratings-number').first()).toHaveText('1')
     })
 
     test('multiple question surveys', async ({ page, context }) => {
@@ -139,18 +139,18 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice1').click()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice2').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice1').click()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice2').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
-        await page.locator('.PostHogSurvey12345').locator('textarea').type('Great job!')
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('textarea').type('Great job!')
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.thank-you-message')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
-        await expect(page.locator('.PostHogSurvey12345').locator('.thank-you-message')).not.toBeVisible()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.thank-you-message')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.thank-you-message')).not.toBeVisible()
 
         await pollUntilEventCaptured(page, 'survey sent')
         const captures = await page.capturedEvents()
@@ -210,11 +210,11 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice3').click()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice0').click()
-        await page.locator('.PostHogSurvey12345').locator('input[type=text]').type('Newsletters')
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice3').click()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice0').click()
+        await page.locator('.PostHogSurvey-12345').locator('input[type=text]').type('Newsletters')
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
         const captures = await page.capturedEvents()
@@ -258,16 +258,16 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice3').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice3').click()
         // TODO: you have to click on the input to activate it, really clicking on the parent should select the input
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice3Open').click()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice3Open').click()
         await page
-            .locator('.PostHogSurvey12345')
+            .locator('.PostHogSurvey-12345')
             .locator('input[type=text]#surveyQuestion0Choice3Open')
             .type('Product engineer')
 
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
         const captures = await page.capturedEvents()
diff --git a/playwright/surveys/response-capture.spec.ts b/playwright/surveys/response-capture.spec.ts
index 7711a52e8e..1e7ee933cc 100644
--- a/playwright/surveys/response-capture.spec.ts
+++ b/playwright/surveys/response-capture.spec.ts
@@ -41,8 +41,8 @@ test.describe('surveys - feedback widget', () => {
 
         await pollUntilEventCaptured(page, 'survey shown')
 
-        await page.locator('.PostHogSurvey123 textarea').type('experiments is awesome!')
-        await page.locator('.PostHogSurvey123 .form-submit').click()
+        await page.locator('.PostHogSurvey-123 textarea').type('experiments is awesome!')
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
         const surveySentEvent = await page
@@ -97,8 +97,8 @@ test.describe('surveys - feedback widget', () => {
             })
         )
 
-        await page.locator('.PostHogSurvey123 textarea').type('experiments is awesome!')
-        await page.locator('.PostHogSurvey123 .form-submit').click()
+        await page.locator('.PostHogSurvey-123 textarea').type('experiments is awesome!')
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
         await pollUntilEventCaptured(page, 'survey sent')
         const surveySentEvent = await page
@@ -141,7 +141,7 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await page.locator('.PostHogSurvey123 .cancel-btn-wrapper').click()
+        await page.locator('.PostHogSurvey-123 .cancel-btn-wrapper').click()
         await pollUntilEventCaptured(page, 'survey dismissed')
     })
 
@@ -167,7 +167,7 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await page.locator('.PostHogSurvey123 .cancel-btn-wrapper').click()
+        await page.locator('.PostHogSurvey-123 .cancel-btn-wrapper').click()
         await pollUntilEventCaptured(page, 'survey dismissed')
         const surveyDismissedEvent = await page
             .capturedEvents()
diff --git a/playwright/surveys/thank-you-message.spec.ts b/playwright/surveys/thank-you-message.spec.ts
index 0c3bbdf01f..f80b4fb2b9 100644
--- a/playwright/surveys/thank-you-message.spec.ts
+++ b/playwright/surveys/thank-you-message.spec.ts
@@ -46,11 +46,11 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123 .ratings-emoji')).toHaveCount(5)
-        await page.locator('.PostHogSurvey123 .ratings-emoji').first().click()
+        await expect(page.locator('.PostHogSurvey-123 .ratings-emoji')).toHaveCount(5)
+        await page.locator('.PostHogSurvey-123 .ratings-emoji').first().click()
 
-        await page.locator('.PostHogSurvey123 .form-submit').click()
-        await expect(page.locator('.PostHogSurvey123 .thank-you-message')).toBeVisible()
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123 .thank-you-message')).toBeVisible()
     })
 
     test('counts down with auto disappear after 5 seconds', async ({ page, context }) => {
@@ -74,12 +74,12 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123 .ratings-emoji')).toHaveCount(5)
-        await page.locator('.PostHogSurvey123 .ratings-emoji').first().click()
-        await page.locator('.PostHogSurvey123 .form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123 .ratings-emoji')).toHaveCount(5)
+        await page.locator('.PostHogSurvey-123 .ratings-emoji').first().click()
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
-        await expect(page.locator('.PostHogSurvey123 .thank-you-message')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123 .thank-you-message')).toBeVisible()
         await page.waitForTimeout(5000)
-        await expect(page.locator('.PostHogSurvey123 .thank-you-message')).not.toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123 .thank-you-message')).not.toBeVisible()
     })
 })
diff --git a/src/__tests__/extensions/surveys.test.ts b/src/__tests__/extensions/surveys.test.ts
index 5df900d2dd..b795136502 100644
--- a/src/__tests__/extensions/surveys.test.ts
+++ b/src/__tests__/extensions/surveys.test.ts
@@ -32,7 +32,7 @@ describe('survey display logic', () => {
         const surveyId = 'randomSurveyId'
         const mockShadow = createShadow(`.survey-${surveyId}-form {}`, surveyId)
         expect(mockShadow.mode).toBe('open')
-        expect(mockShadow.host.className).toBe(`PostHogSurvey${surveyId}`)
+        expect(mockShadow.host.className).toBe(`PostHogSurvey-${surveyId}`)
     })
 
     const mockSurveys: Survey[] = [
@@ -145,7 +145,7 @@ describe('usePopupVisibility', () => {
     test('should hide popup when PHSurveyClosed event is dispatched', () => {
         const { result } = renderHook(() => usePopupVisibility(mockSurvey, mockPostHog, 0, false, removeSurvey))
         act(() => {
-            window.dispatchEvent(new Event('PHSurveyClosed'))
+            window.dispatchEvent(new CustomEvent('PHSurveyClosed', { detail: { surveyId: mockSurvey.id } }))
         })
         expect(result.current.isPopupVisible).toBe(false)
     })
@@ -161,7 +161,7 @@ describe('usePopupVisibility', () => {
 
         const { result } = renderHook(() => usePopupVisibility(mockSurvey, mockPostHog, 0, false, removeSurvey))
         act(() => {
-            window.dispatchEvent(new Event('PHSurveySent'))
+            window.dispatchEvent(new CustomEvent('PHSurveySent', { detail: { surveyId: mockSurvey.id } }))
         })
 
         expect(result.current.isSurveySent).toBe(true)
@@ -457,14 +457,17 @@ describe('SurveyManager', () => {
         surveyManager.getTestAPI().addSurveyToFocus('survey1')
         surveyManager.callSurveysAndEvaluateDisplayLogic()
 
-        expect(mockPostHog.surveys.getSurveys).toHaveBeenCalledTimes(1)
-        expect(surveyManager.getTestAPI().surveyInFocus).toBe('survey1')
-
         const handlePopoverSurveyMock = jest
             .spyOn(surveyManager as any, '_handlePopoverSurvey')
             .mockImplementation(() => {})
 
+        expect(mockPostHog.surveys.getSurveys).toHaveBeenCalledTimes(1)
+        expect(surveyManager.getTestAPI().surveyInFocus).toBe('survey1')
+        expect(handlePopoverSurveyMock).not.toHaveBeenCalled()
+
         surveyManager.getTestAPI().removeSurveyFromFocus('survey1')
+        jest.spyOn(surveyManager as any, '_canShowNextEventBasedSurvey').mockReturnValue(true)
+
         surveyManager.callSurveysAndEvaluateDisplayLogic()
 
         expect(mockPostHog.surveys.getSurveys).toHaveBeenCalledTimes(2)
diff --git a/src/extensions/surveys-widget.ts b/src/extensions/surveys-widget.ts
index 279ae4d671..c90d13a821 100644
--- a/src/extensions/surveys-widget.ts
+++ b/src/extensions/surveys-widget.ts
@@ -1,14 +1,14 @@
 import { PostHog } from '../posthog-core'
 import { Survey } from '../posthog-surveys-types'
 import { document as _document } from '../utils/globals'
-import { SURVEY_DEFAULT_Z_INDEX } from './surveys/surveys-extension-utils'
+import { getSurveyContainerClass, SURVEY_DEFAULT_Z_INDEX } from './surveys/surveys-extension-utils'
 import { prepareStylesheet } from './utils/stylesheet-loader'
 
 // We cast the types here which is dangerous but protected by the top level generateSurveys call
 const document = _document as Document
 
 export function retrieveWidgetShadow(survey: Survey, posthog?: PostHog) {
-    const widgetClassName = `PostHogWidget${survey.id}`
+    const widgetClassName = getSurveyContainerClass(survey)
     const existingDiv = document.querySelector(`.${widgetClassName}`) as HTMLDivElement | null
 
     if (existingDiv && existingDiv.shadowRoot) {
diff --git a/src/extensions/surveys.tsx b/src/extensions/surveys.tsx
index afb120a6de..d4cbdaeca4 100644
--- a/src/extensions/surveys.tsx
+++ b/src/extensions/surveys.tsx
@@ -42,6 +42,7 @@ import {
     doesSurveyUrlMatch,
     getContrastingTextColor,
     getDisplayOrderQuestions,
+    getSurveyContainerClass,
     getSurveyResponseKey,
     getSurveySeen,
     hasWaitPeriodPassed,
@@ -56,10 +57,6 @@ import { prepareStylesheet } from './utils/stylesheet-loader'
 const window = _window as Window & typeof globalThis
 const document = _document as Document
 
-function getPosthogWidgetClass(surveyId: string) {
-    return `.PostHogWidget${surveyId}`
-}
-
 const DISPATCH_FEEDBACK_WIDGET_EVENT = 'ph:show_survey_widget'
 
 function getRatingBucketForResponseValue(responseValue: number, scale: number) {
@@ -779,12 +776,18 @@ export function usePopupVisibility(
             return
         }
 
-        const handleSurveyClosed = () => {
+        const handleSurveyClosed = (event: CustomEvent) => {
+            if (event.detail.surveyId !== survey.id) {
+                return
+            }
             removeSurveyFromFocus(survey.id)
             setIsPopupVisible(false)
         }
 
-        const handleSurveySent = () => {
+        const handleSurveySent = (event: CustomEvent) => {
+            if (event.detail.surveyId !== survey.id) {
+                return
+            }
             if (!survey.appearance?.displayThankYouMessage) {
                 removeSurveyFromFocus(survey.id)
                 setIsPopupVisible(false)
@@ -817,7 +820,7 @@ export function usePopupVisibility(
             localStorage.setItem('lastSeenSurveyDate', new Date().toISOString())
             setTimeout(() => {
                 const inputField = document
-                    .querySelector(getPosthogWidgetClass(survey.id))
+                    .querySelector(getSurveyContainerClass(survey, true))
                     ?.shadowRoot?.querySelector('textarea, input[type="text"]') as HTMLElement
                 if (inputField) {
                     inputField.focus()
@@ -825,8 +828,8 @@ export function usePopupVisibility(
             }, 100)
         }
 
-        addEventListener(window, 'PHSurveyClosed', handleSurveyClosed)
-        addEventListener(window, 'PHSurveySent', handleSurveySent)
+        addEventListener(window, 'PHSurveyClosed', handleSurveyClosed as EventListener)
+        addEventListener(window, 'PHSurveySent', handleSurveySent as EventListener)
 
         if (millisecondDelay > 0) {
             // This path is only used for direct usage of SurveyPopup,
@@ -834,15 +837,15 @@ export function usePopupVisibility(
             const timeoutId = setTimeout(showSurvey, millisecondDelay)
             return () => {
                 clearTimeout(timeoutId)
-                window.removeEventListener('PHSurveyClosed', handleSurveyClosed)
-                window.removeEventListener('PHSurveySent', handleSurveySent)
+                window.removeEventListener('PHSurveyClosed', handleSurveyClosed as EventListener)
+                window.removeEventListener('PHSurveySent', handleSurveySent as EventListener)
             }
         } else {
             // This is the path used for surveys managed by SurveyManager
             showSurvey()
             return () => {
-                window.removeEventListener('PHSurveyClosed', handleSurveyClosed)
-                window.removeEventListener('PHSurveySent', handleSurveySent)
+                window.removeEventListener('PHSurveyClosed', handleSurveyClosed as EventListener)
+                window.removeEventListener('PHSurveySent', handleSurveySent as EventListener)
             }
         }
     }, [])
diff --git a/src/extensions/surveys/surveys-extension-utils.tsx b/src/extensions/surveys/surveys-extension-utils.tsx
index 26f4213a4d..cefd62c1e5 100644
--- a/src/extensions/surveys/surveys-extension-utils.tsx
+++ b/src/extensions/surveys/surveys-extension-utils.tsx
@@ -559,7 +559,7 @@ export const defaultBackgroundColor = '#eeeded'
 
 export const createShadow = (styleSheet: string, surveyId: string, element?: Element, posthog?: PostHog) => {
     const div = document.createElement('div')
-    div.className = `PostHogSurvey${surveyId}`
+    div.className = getSurveyContainerClass({ id: surveyId })
     const shadow = div.attachShadow({ mode: 'open' })
     if (styleSheet) {
         const styleElement = prepareStylesheet(document, styleSheet, posthog)
@@ -598,7 +598,7 @@ export const sendSurveyEvent = (
             [getSurveyInteractionProperty(survey, 'responded')]: true,
         },
     })
-    window.dispatchEvent(new Event('PHSurveySent'))
+    window.dispatchEvent(new CustomEvent('PHSurveySent', { detail: { surveyId: survey.id } }))
 }
 
 export const dismissedSurveyEvent = (survey: Survey, posthog?: PostHog, readOnly?: boolean) => {
@@ -621,7 +621,7 @@ export const dismissedSurveyEvent = (survey: Survey, posthog?: PostHog, readOnly
         },
     })
     localStorage.setItem(getSurveySeenKey(survey), 'true')
-    window.dispatchEvent(new Event('PHSurveyClosed'))
+    window.dispatchEvent(new CustomEvent('PHSurveyClosed', { detail: { surveyId: survey.id } }))
 }
 
 // Use the Fisher-yates algorithm to shuffle this array
@@ -814,3 +814,8 @@ export function doesSurveyMatchSelector(survey: Survey): boolean {
     }
     return !!document?.querySelector(survey.conditions.selector)
 }
+
+export function getSurveyContainerClass(survey: Pick<Survey, 'id'>, asSelector = false): string {
+    const className = `PostHogSurvey-${survey.id}`
+    return asSelector ? `.${className}` : className
+}


Reviews:
user: login: greptile-apps[bot]
body: 
## PR Summary

This PR makes two key changes to the PostHog JavaScript SDK's survey functionality:

- Fixes a bug where survey events (sent/dismissed) were affecting all visible surveys by adding survey ID checks to event handlers
- Standardizes survey container class naming from type-specific formats (`PostHogWidget${surveyId}` or `PostHogSurvey${surveyId}`) to unified `PostHogSurvey-${surveyId}`

Key changes:
- Added CustomEvent with surveyId in event detail for proper event scoping
- Updated all survey selectors across test files to use new `PostHogSurvey-${surveyId}` format
- Added new test cases verifying multiple surveys can be shown without interference
- Modified event handlers to check survey IDs before taking action
- Added specific Playwright test scripts for survey features

The changes look well-tested and maintain backward compatibility while fixing the multiple survey interaction issue.

<sub>10 file(s) reviewed, 4 comment(s)</sub>
<sub>[Edit PR Review Bot Settings](https://app.greptile.com/review/github) | [Greptile](https://greptile.com?utm_source=greptile_expert&utm_medium=github&utm_campaign=code_reviews&utm_content=posthog-js_1924)</sub>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-27T17:11:42Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-27T17:26:18Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-27T17:26:25Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-27T18:24:32Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-27T18:51:03Z
user: login: marandaneto
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T13:52:44Z
user: login: marandaneto
body: left a question otherwise LGTM
state: APPROVED
author_association: MEMBER
submitted_at: 2025-04-28T13:52:55Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T15:13:10Z
user: login: lucasheriques
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T15:20:24Z

Review comments:
diff_hunk: @@ -279,41 +280,164 @@ test.describe('surveys - feedback widget', () => {
         await surveysAPICall
 
         // 1. Check that the survey widget is rendered
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toBeVisible()
 
         // 2. Open the survey
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // 3. Answer the survey
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('first submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // 4. Check for thank you message
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toHaveText('Thank you!')
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toHaveText('Thank you!')
 
         // Verify the event was sent
         await pollUntilEventCaptured(page, 'survey sent')
 
         // 5. Close the thank you message and click the survey tab again
-        await page.locator('.PostHogWidget123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).not.toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
 
         // Open the survey again
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
 
         // 6. Verify survey is rendered again
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // Submit again with different text
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('second submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('second submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // Verify thank you message appears again
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
 
         // Verify second event was sent
         await pollUntilEventCaptured(page, 'survey sent')
     })
+
+    test('if multiple surveys being shown, sending one of them does not close the other one', async ({
+        page,
+        context,
+    }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // fill in first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
+
+        await pollUntilEventCaptured(page, 'survey sent')
+
+        // click on the first survey confirmation message
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+    })
+
+    test('if multiple surveys being shown, closing one does not close the other', async ({ page, context }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // close first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-cancel').click()
+
+        await pollUntilEventCaptured(page, 'survey dismissed')
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
path: playwright/surveys/feedback-widget.spec.ts
user: login: greptile-apps[bot]
body: style: Duplicate comment - this line repeats the check from line 438
created_at: 2025-04-27T17:09:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -8,7 +8,7 @@ import { prepareStylesheet } from './utils/stylesheet-loader'
 const document = _document as Document
 
 export function retrieveWidgetShadow(survey: Survey, posthog?: PostHog) {
-    const widgetClassName = `PostHogWidget${survey.id}`
+    const widgetClassName = `PostHogSurvey-${survey.id}`
path: src/extensions/surveys-widget.ts
user: login: greptile-apps[bot]
body: style: Consider using a constant for the 'PostHogSurvey-' prefix to maintain consistency and make future updates easier
created_at: 2025-04-27T17:10:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,12 +74,12 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123 .ratings-emoji')).toHaveCount(5)
-        await page.locator('.PostHogSurvey123 .ratings-emoji').first().click()
-        await page.locator('.PostHogSurvey123 .form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123 .ratings-emoji')).toHaveCount(5)
+        await page.locator('.PostHogSurvey-123 .ratings-emoji').first().click()
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
-        await expect(page.locator('.PostHogSurvey123 .thank-you-message')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123 .thank-you-message')).toBeVisible()
         await page.waitForTimeout(5000)
path: playwright/surveys/thank-you-message.spec.ts
user: login: greptile-apps[bot]
body: style: Consider using a constant for the timeout value (5000ms) to match the actual configuration in the survey appearance settings
created_at: 2025-04-27T17:10:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -139,18 +139,18 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice1').click()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice2').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice1').click()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice2').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
-        await page.locator('.PostHogSurvey12345').locator('textarea').type('Great job!')
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('textarea').type('Great job!')
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
path: playwright/surveys/question-types.spec.ts
user: login: greptile-apps[bot]
body: style: Multiple consecutive clicks on form-submit without waiting for response could lead to race conditions. Consider adding wait assertions between clicks.
created_at: 2025-04-27T17:10:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,12 +74,12 @@ test.describe('surveys - feedback widget', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey123 .ratings-emoji')).toHaveCount(5)
-        await page.locator('.PostHogSurvey123 .ratings-emoji').first().click()
-        await page.locator('.PostHogSurvey123 .form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123 .ratings-emoji')).toHaveCount(5)
+        await page.locator('.PostHogSurvey-123 .ratings-emoji').first().click()
+        await page.locator('.PostHogSurvey-123 .form-submit').click()
 
-        await expect(page.locator('.PostHogSurvey123 .thank-you-message')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123 .thank-you-message')).toBeVisible()
         await page.waitForTimeout(5000)
path: playwright/surveys/thank-you-message.spec.ts
user: login: lucasheriques
body: no need for tests
created_at: 2025-04-27T17:26:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -139,18 +139,18 @@ test.describe('surveys - core display logic', () => {
         await start(startOptions, page, context)
         await surveysAPICall
 
-        await expect(page.locator('.PostHogSurvey12345').locator('.survey-form')).toBeVisible()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice1').click()
-        await page.locator('.PostHogSurvey12345').locator('#surveyQuestion0Choice2').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-12345').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice1').click()
+        await page.locator('.PostHogSurvey-12345').locator('#surveyQuestion0Choice2').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
 
-        await page.locator('.PostHogSurvey12345').locator('textarea').type('Great job!')
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
-        await page.locator('.PostHogSurvey12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('textarea').type('Great job!')
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-12345').locator('.form-submit').click()
path: playwright/surveys/question-types.spec.ts
user: login: lucasheriques
body: this is expected
created_at: 2025-04-27T17:26:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -279,41 +280,161 @@ test.describe('surveys - feedback widget', () => {
         await surveysAPICall
 
         // 1. Check that the survey widget is rendered
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toBeVisible()
 
         // 2. Open the survey
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // 3. Answer the survey
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('first submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // 4. Check for thank you message
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toHaveText('Thank you!')
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toHaveText('Thank you!')
 
         // Verify the event was sent
         await pollUntilEventCaptured(page, 'survey sent')
 
         // 5. Close the thank you message and click the survey tab again
-        await page.locator('.PostHogWidget123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).not.toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
 
         // Open the survey again
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
 
         // 6. Verify survey is rendered again
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // Submit again with different text
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('second submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('second submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // Verify thank you message appears again
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
 
         // Verify second event was sent
         await pollUntilEventCaptured(page, 'survey sent')
     })
+
+    test('if multiple surveys being shown, sending one of them does not close the other one', async ({
path: playwright/surveys/feedback-widget.spec.ts
user: login: lucasheriques
body: start of the new tests that handles the bug
created_at: 2025-04-27T18:24:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -279,41 +280,161 @@ test.describe('surveys - feedback widget', () => {
         await surveysAPICall
 
         // 1. Check that the survey widget is rendered
-        await expect(page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab')).toBeVisible()
 
         // 2. Open the survey
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // 3. Answer the survey
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('first submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // 4. Check for thank you message
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toHaveText('Thank you!')
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toHaveText('Thank you!')
 
         // Verify the event was sent
         await pollUntilEventCaptured(page, 'survey sent')
 
         // 5. Close the thank you message and click the survey tab again
-        await page.locator('.PostHogWidget123').locator('.form-submit').click()
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).not.toBeVisible()
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
 
         // Open the survey again
-        await page.locator('.PostHogWidget123').locator('.ph-survey-widget-tab').click()
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
 
         // 6. Verify survey is rendered again
-        await expect(page.locator('.PostHogWidget123').locator('.survey-form')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
 
         // Submit again with different text
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('textarea').fill('second submission')
-        await page.locator('.PostHogWidget123').locator('.survey-form').locator('.form-submit').click()
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('second submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
 
         // Verify thank you message appears again
-        await expect(page.locator('.PostHogWidget123').locator('.thank-you-message-header')).toBeVisible()
+        await expect(page.locator('.PostHogSurvey-123').locator('.thank-you-message-header')).toBeVisible()
 
         // Verify second event was sent
         await pollUntilEventCaptured(page, 'survey sent')
     })
+
+    test('if multiple surveys being shown, sending one of them does not close the other one', async ({
+        page,
+        context,
+    }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // fill in first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('textarea').fill('first submission')
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-submit').click()
+
+        await pollUntilEventCaptured(page, 'survey sent')
+
+        // click on the first survey confirmation message
+        await page.locator('.PostHogSurvey-123').locator('.form-submit').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+    })
+
+    test('if multiple surveys being shown, closing one does not close the other', async ({ page, context }) => {
+        const surveysAPICall = page.route('**/surveys/**', async (route) => {
+            await route.fulfill({
+                json: {
+                    surveys: [
+                        {
+                            id: '123',
+                            name: 'Test survey',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                widgetLabel: 'Feedback',
+                                widgetType: 'tab',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                        {
+                            id: '456',
+                            name: 'Test survey 2',
+                            type: 'widget',
+                            start_date: '2021-01-01T00:00:00Z',
+                            questions: [openTextQuestion],
+                            appearance: {
+                                position: 'next_to_trigger',
+                                widgetSelector: '.test-surveys',
+                                widgetType: 'selector',
+                                displayThankYouMessage: true,
+                                thankyouMessageHeader: 'Thank you!',
+                            },
+                        },
+                    ],
+                },
+            })
+        })
+
+        await start(startOptions, page, context)
+        await surveysAPICall
+
+        // click on the second survey trigger
+        await page.locator('.test-surveys').click()
+        await expect(page.locator('.PostHogSurvey-456').locator('.survey-form')).toBeVisible()
+
+        await page.locator('.PostHogSurvey-123').locator('.ph-survey-widget-tab').click()
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).toBeVisible()
+
+        // close first survey
+        await page.locator('.PostHogSurvey-123').locator('.survey-form').locator('.form-cancel').click()
+
+        await pollUntilEventCaptured(page, 'survey dismissed')
+
+        // check if the second survey is still visible
+        await expect(page.locator('.PostHogSurvey-123').locator('.survey-form')).not.toBeVisible()
+    })
path: playwright/surveys/feedback-widget.spec.ts
user: login: lucasheriques
body: end of the new tests that handles the bug
created_at: 2025-04-27T18:51:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -817,32 +820,32 @@ export function usePopupVisibility(
             localStorage.setItem('lastSeenSurveyDate', new Date().toISOString())
             setTimeout(() => {
                 const inputField = document
-                    .querySelector(getPosthogWidgetClass(survey.id))
+                    .querySelector(`.${getSurveyContainerClass(survey)}`)
path: src/extensions/surveys.tsx
user: login: marandaneto
body: should `getSurveyContainerClass` already start with the `.` so you don't have to concatenate in multiple places? it was like this before as well
created_at: 2025-04-28T13:52:44Z
author_association: MEMBER
diff_hunk: @@ -817,32 +820,32 @@ export function usePopupVisibility(
             localStorage.setItem('lastSeenSurveyDate', new Date().toISOString())
             setTimeout(() => {
                 const inputField = document
-                    .querySelector(getPosthogWidgetClass(survey.id))
+                    .querySelector(`.${getSurveyContainerClass(survey)}`)
path: src/extensions/surveys.tsx
user: login: lucasheriques
body: yeah there's two places where it requires the . vs one that doesn't, so will change
created_at: 2025-04-28T15:13:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -817,32 +820,32 @@ export function usePopupVisibility(
             localStorage.setItem('lastSeenSurveyDate', new Date().toISOString())
             setTimeout(() => {
                 const inputField = document
-                    .querySelector(getPosthogWidgetClass(survey.id))
+                    .querySelector(`.${getSurveyContainerClass(survey)}`)
path: src/extensions/surveys.tsx
user: login: lucasheriques
body: i changed instead so the function has the option to return the [class as a selector](https://github.com/PostHog/posthog-js/pull/1924/commits/e1f6dca0de4a4ec8734e7c0b4db6a85756a9be6f)
created_at: 2025-04-28T15:20:24Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-04-27T17:08:57Z
body: [vc]: #qEZ8LK/iphG2WrFPi56HjsE0YaKNmoP3ok3ebgeKbhI=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJwb3N0aG9nLWpzIiwiaW5zcGVjdG9yVXJsIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3Bvc3QtaG9nL3Bvc3Rob2ctanMvNXVOeEs5MVdmN0RpMWRFU3d5OGE3aldpQlplOCIsInByZXZpZXdVcmwiOiJwb3N0aG9nLWpzLWdpdC1maXgtcHJldmVudC1zdXJ2ZXktZXZlbnRzLXRvLWFmZi02YTMxYmEtcG9zdC1ob2cudmVyY2VsLmFwcCIsIm5leHRDb21taXRTdGF0dXMiOiJERVBMT1lFRCIsInJvb3REaXJlY3RvcnkiOiJwbGF5Z3JvdW5kL25leHRqcyJ9XX0=
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Updated (UTC) |
| :--- | :----- | :------ | :------ |
| **posthog-js** | ✅ Ready ([Inspect](https://vercel.com/post-hog/posthog-js/5uNxK91Wf7Di1dESwy8a7jWiBZe8)) | [Visit Preview](https://posthog-js-git-fix-prevent-survey-events-to-aff-6a31ba-post-hog.vercel.app) | Apr 28, 2025 3:23pm |


author_association: NONE
user: login: github-actions[bot]
created_at: 2025-04-27T17:11:33Z
body: [Download bundle size visualization](https://github.com/PostHog/posthog-js/actions/runs/14711445236/artifacts/3022997402)
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-04-27T17:16:04Z
body: **Size Change:** +1.47 kB (+0.04%) 

**Total Size:** 3.63 MB

| Filename | Size | Change |
| :--- | :---: | :---: |
| `dist/all-external-dependencies.js` | 219 kB | +179 B (+0.08%) |
| `dist/array.full.es5.js` | 307 kB | +183 B (+0.06%) |
| `dist/array.full.js` | 386 kB | +179 B (+0.05%) |
| `dist/array.full.no-external.js` | 385 kB | +179 B (+0.05%) |
| `dist/module.full.js` | 386 kB | +179 B (+0.05%) |
| `dist/module.full.no-external.js` | 385 kB | +179 B (+0.05%) |
| `dist/surveys-preview.js` | 64.9 kB | +212 B (+0.33%) |
| `dist/surveys.js` | 74.6 kB | +179 B (+0.24%) |

<details><summary>ℹ️ <strong>View Unchanged</strong></summary>

| Filename | Size |
| :--- | :---: |
| `dist/array.js` | 185 kB |
| `dist/array.no-external.js` | 184 kB |
| `dist/customizations.full.js` | 11.6 kB |
| `dist/dead-clicks-autocapture.js` | 14.4 kB |
| `dist/exception-autocapture.js` | 10.4 kB |
| `dist/external-scripts-loader.js` | 2.75 kB |
| `dist/main.js` | 187 kB |
| `dist/module.js` | 186 kB |
| `dist/module.no-external.js` | 185 kB |
| `dist/posthog-recorder.js` | 211 kB |
| `dist/recorder-v2.js` | 115 kB |
| `dist/recorder.js` | 115 kB |
| `dist/tracing-headers.js` | 1.76 kB |
| `dist/web-vitals.js` | 10.4 kB |

</details>



<a href="https://github.com/preactjs/compressed-size-action"><sub>compressed-size-action</sub></a>
author_association: CONTRIBUTOR