Compare commits

..

3 Commits

Author SHA1 Message Date
Piotr Gaczkowski 4b3a41272e fix: Remove alias 2025-07-31 15:22:22 +02:00
Piotr Gaczkowski 83a38c242e fix: Satisfy actionlint 2025-07-31 14:47:48 +02:00
Piotr Gaczkowski c4181a1c9c chore(CI): Don't run container tests on infra code changes 2025-07-31 14:13:04 +02:00
13 changed files with 82 additions and 148 deletions
@@ -4,9 +4,15 @@ on:
pull_request:
branches:
- main
paths-ignore:
- helm-chart/**
- infra/**
merge_group:
branches:
- main
paths-ignore:
- helm-chart/**
- infra/**
workflow_dispatch:
permissions:
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "Letztes Quartal",
"last_year": "Letztes Jahr",
"no_responses_found": "Keine Antworten gefunden",
"only_completed": "Nur vollständige Antworten",
"other_values_found": "Andere Werte gefunden",
"overall": "Insgesamt",
"qr_code": "QR-Code",
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "Last quarter",
"last_year": "Last year",
"no_responses_found": "No responses found",
"only_completed": "Only completed",
"other_values_found": "Other values found",
"overall": "Overall",
"qr_code": "QR code",
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "dernier trimestre",
"last_year": "l'année dernière",
"no_responses_found": "Aucune réponse trouvée",
"only_completed": "Uniquement terminé",
"other_values_found": "D'autres valeurs trouvées",
"overall": "Globalement",
"qr_code": "Code QR",
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "Último trimestre",
"last_year": "Último ano",
"no_responses_found": "Nenhuma resposta encontrada",
"only_completed": "Somente concluído",
"other_values_found": "Outros valores encontrados",
"overall": "No geral",
"qr_code": "Código QR",
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "Último trimestre",
"last_year": "Ano passado",
"no_responses_found": "Nenhuma resposta encontrada",
"only_completed": "Apenas concluído",
"other_values_found": "Outros valores encontrados",
"overall": "Geral",
"qr_code": "Código QR",
+1
View File
@@ -1813,6 +1813,7 @@
"last_quarter": "上一季",
"last_year": "去年",
"no_responses_found": "找不到回應",
"only_completed": "僅已完成",
"other_values_found": "找到其他值",
"overall": "整體",
"qr_code": "QR 碼",
+1 -1
View File
@@ -132,7 +132,7 @@
"ua-parser-js": "2.0.3",
"uuid": "11.1.0",
"webpack": "5.99.8",
"xlsx": "file:vendor/xlsx-0.20.3.tgz",
"xlsx": "0.18.5",
"zod": "3.24.4",
"zod-openapi": "4.2.4"
},
BIN
View File
Binary file not shown.
-1
View File
@@ -49,7 +49,6 @@
"xm-and-surveys/surveys/general-features/variables",
"xm-and-surveys/surveys/general-features/hide-back-button",
"xm-and-surveys/surveys/general-features/email-followups",
"xm-and-surveys/surveys/general-features/quota-management",
"xm-and-surveys/surveys/general-features/spam-protection"
]
},
@@ -1,129 +0,0 @@
---
title: "Quota Management"
description: "Control response collection by setting limits on specific segments to ensure balanced and representative survey datasets."
icon: "chart-pie"
---
## Overview
Quota Management allows you to set limits on the number of responses collected for specific segments or criteria in your survey. This feature helps ensure you collect a balanced and representative dataset while preventing oversaturation of certain response types.
<Note type="warning">
Quota Management is currently in beta and only available to select customers.
</Note>
<Note>
Quota Management is part of the [Enterprise Edition](/self-hosting/advanced/license).
</Note>
### Key benefits
- **Balanced Data Collection**: Ensure your survey responses are evenly distributed across different segments
- **Cost Control**: Prevent collecting more responses than needed from specific groups
- **Quality Assurance**: Maintain data quality by avoiding homogeneous response patterns
- **Automated Management**: Automatically stop collecting responses when quotas are met
### How Quota Management works
When you set up quotas for your survey, Formbricks automatically tracks responses against your defined limits. Once a quota is reached, the system can:
- Prevent new responses from that segment
- Skip respondents to the end of the survey
- Redirect respondents to a custom end screen
## Setting up Quotas
In the first step, you need to define the criteria for the quota:
<Steps>
<Step title="Name the quota">
Create a Quota and label it e.g. "Mobile Phone Users in Europe"
</Step>
<Step title="Set quota limit">
Set numerical limits for each hidden field value combination e.g. 500
</Step>
<Step title="Define inclusion criteria">
Choose a distinct set of answers to survey questions, variable values or hidden fields. Responses who match this set will be included in the quota.
</Step>
<Step title="Configure actions">
Choose what happens when this Quota is met (e.g. skip to specific end screen)
</Step>
</Steps>
## Quota actions
Configure what happens when a quota reaches its limit:
<Tabs>
<Tab title="Skip to End">
Jump respondents directly to the survey completion page
</Tab>
<Tab title="Custom Redirect (soon)">
Redirect respondents to a custom thank you page or alternative survey
</Tab>
</Tabs>
## Counting against Quotas
### 1. Count by Hidden Field value
Determine if a response falls in or out of a Quota based on hidden field values passed through URL parameters:
```
https://your-survey-url.com/s/abc123?product=credit-card&region=europe
```
### 2. Quota by survey responses
Create quotas based on specific answers to survey questions:
<Tabs>
<Tab title="Single Question Quota">
Set quotas for individual answer options:
- Question: "What is your gender?"
- Quota: 500 responses for "Male", 500 responses for "Female"
</Tab>
<Tab title="Multi-Question Quota">
Combine multiple question responses:
- Criteria: Age group "25-34" AND Location "Urban"
- Quota: 200 responses matching both criteria
</Tab>
</Tabs>
### 3. Multi-criteria quotas
Create complex quotas using multiple conditions:
<CodeGroup>
```example "Hidden Field + Response Combination"
Hidden Field: product = "mobile"
AND
Question Response: satisfaction = "very satisfied"
```
```example "Multiple Response Criteria"
Question 1: age_group = "18-25"
AND
Question 2: location = "urban"
AND
Question 3: income = "high"
Quota Limit: 50 responses
```
</CodeGroup>
### Partial vs. complete responses
<Info>
By default, Quota Management includes partial responses in quota counts. You can change this behavior by configuring the quota to only count complete responses.
</Info>
This means if a respondent starts but doesn't complete the survey, they may still count toward your quota if they've answered the qualifying questions.
## Quota monitoring
<Card title="Live Quota Status" icon="chart-line">
Monitor your quotas in real-time through the dashboard in the survey summary:
- **Current Count**: See how many responses each quota has collected
- **Progress Bars**: Visual representation of quota completion
- **Status Indicators**: Active, completed, or paused quota status
</Card>
+2 -11
View File
@@ -137,7 +137,8 @@ module "eks" {
cluster_version = "1.32"
enable_cluster_creator_admin_permissions = false
cluster_endpoint_public_access = false
cluster_endpoint_public_access = true # TEMPORARY: Enable for deployments until Tailscale is fixed by new DevOps engineer
cluster_endpoint_public_access_cidrs = ["0.0.0.0/0"] # TEMPORARY: Will revert to private + Tailscale access
cloudwatch_log_group_retention_in_days = 365
cluster_addons = {
@@ -531,13 +532,3 @@ module "formbricks_app_iam_role" {
}
}
}
module "account_public_access" {
source = "terraform-aws-modules/s3-bucket/aws//modules/account-public-access"
version = "4.6.0"
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
+67 -6
View File
@@ -442,8 +442,8 @@ importers:
specifier: 5.99.8
version: 5.99.8(esbuild@0.25.4)
xlsx:
specifier: file:vendor/xlsx-0.20.3.tgz
version: file:apps/web/vendor/xlsx-0.20.3.tgz
specifier: 0.18.5
version: 0.18.5
zod:
specifier: 3.24.4
version: 3.24.4
@@ -4661,6 +4661,10 @@ packages:
engines: {node: '>=0.4.0'}
hasBin: true
adler-32@1.3.1:
resolution: {integrity: sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==}
engines: {node: '>=0.8'}
agent-base@6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
engines: {node: '>= 6.0.0'}
@@ -5039,6 +5043,10 @@ packages:
caniuse-lite@1.0.30001731:
resolution: {integrity: sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==}
cfb@1.2.2:
resolution: {integrity: sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==}
engines: {node: '>=0.8'}
chai@5.2.1:
resolution: {integrity: sha512-5nFxhUrX0PqtyogoYOA8IPswy5sZFTOsBFl/9bNsmDLgsxYTzSZQJDPppDnZPTQbzSEm0hqGjWPzRemQCYbD6A==}
engines: {node: '>=18'}
@@ -5140,6 +5148,10 @@ packages:
react: ^18 || ^19 || ^19.0.0-rc
react-dom: ^18 || ^19 || ^19.0.0-rc
codepage@1.15.0:
resolution: {integrity: sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==}
engines: {node: '>=0.8'}
color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
@@ -5242,6 +5254,11 @@ packages:
typescript:
optional: true
crc-32@1.2.2:
resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
engines: {node: '>=0.8'}
hasBin: true
create-require@1.1.1:
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
@@ -6037,6 +6054,10 @@ packages:
forwarded-parse@2.1.2:
resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==}
frac@1.1.2:
resolution: {integrity: sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==}
engines: {node: '>=0.8'}
fraction.js@4.3.7:
resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==}
@@ -8481,6 +8502,10 @@ packages:
resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==}
engines: {node: '>= 0.6'}
ssf@0.11.2:
resolution: {integrity: sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==}
engines: {node: '>=0.8'}
ssri@8.0.1:
resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==}
engines: {node: '>= 8'}
@@ -9344,10 +9369,18 @@ packages:
wide-align@1.1.5:
resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==}
wmf@1.0.2:
resolution: {integrity: sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==}
engines: {node: '>=0.8'}
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
engines: {node: '>=0.10.0'}
word@0.3.0:
resolution: {integrity: sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==}
engines: {node: '>=0.8'}
wrap-ansi@6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
@@ -9383,9 +9416,8 @@ packages:
resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
engines: {node: '>=18'}
xlsx@file:apps/web/vendor/xlsx-0.20.3.tgz:
resolution: {integrity: sha512-oLDq3jw7AcLqKWH2AhCpVTZl8mf6X2YReP+Neh0SJUzV/BdZYjth94tG5toiMB1PPrYtxOCfaoUCkvtuH+3AJA==, tarball: file:apps/web/vendor/xlsx-0.20.3.tgz}
version: 0.20.3
xlsx@0.18.5:
resolution: {integrity: sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==}
engines: {node: '>=0.8'}
hasBin: true
@@ -14605,6 +14637,8 @@ snapshots:
acorn@8.15.0: {}
adler-32@1.3.1: {}
agent-base@6.0.2:
dependencies:
debug: 4.4.1
@@ -15015,6 +15049,11 @@ snapshots:
caniuse-lite@1.0.30001731: {}
cfb@1.2.2:
dependencies:
adler-32: 1.3.1
crc-32: 1.2.2
chai@5.2.1:
dependencies:
assertion-error: 2.0.1
@@ -15117,6 +15156,8 @@ snapshots:
- '@types/react'
- '@types/react-dom'
codepage@1.15.0: {}
color-convert@1.9.3:
dependencies:
color-name: 1.1.3
@@ -15208,6 +15249,8 @@ snapshots:
optionalDependencies:
typescript: 5.8.3
crc-32@1.2.2: {}
create-require@1.1.1: {}
cross-spawn@7.0.6:
@@ -16179,6 +16222,8 @@ snapshots:
forwarded-parse@2.1.2: {}
frac@1.1.2: {}
fraction.js@4.3.7: {}
framer-motion@12.10.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
@@ -18805,6 +18850,10 @@ snapshots:
sqlstring@2.3.3: {}
ssf@0.11.2:
dependencies:
frac: 1.1.2
ssri@8.0.1:
dependencies:
minipass: 3.3.6
@@ -19750,8 +19799,12 @@ snapshots:
string-width: 4.2.3
optional: true
wmf@1.0.2: {}
word-wrap@1.2.5: {}
word@0.3.0: {}
wrap-ansi@6.2.0:
dependencies:
ansi-styles: 4.3.0
@@ -19784,7 +19837,15 @@ snapshots:
dependencies:
is-wsl: 3.1.0
xlsx@file:apps/web/vendor/xlsx-0.20.3.tgz: {}
xlsx@0.18.5:
dependencies:
adler-32: 1.3.1
cfb: 1.2.2
codepage: 1.15.0
crc-32: 1.2.2
ssf: 0.11.2
wmf: 1.0.2
word: 0.3.0
xml-crypto@6.1.2:
dependencies: