Compare commits

..

28 Commits

Author SHA1 Message Date
pandeymangg
2254c24cad fix: github action 2024-05-07 16:41:46 +05:30
pandeymangg
0f28cea7c8 fix: github action 2024-05-07 16:38:47 +05:30
pandeymangg
868ee71e34 fix: github action 2024-05-07 16:33:29 +05:30
pandeymangg
1dbbaca8fd fix: github action 2024-05-07 16:32:06 +05:30
pandeymangg
8b895b4b43 Merge branch 'main' into piyush/enterprise-license-check 2024-05-07 15:44:14 +05:30
pandeymangg
f81eae3691 fix: github action 2024-05-07 14:59:32 +05:30
pandeymangg
317013eee7 fix 2024-05-07 14:25:26 +05:30
pandeymangg
d19470f71a fix: e2e enbv 2024-05-07 13:56:21 +05:30
pandeymangg
3bf5693af1 fix: adds e2e check fallback for test environment 2024-05-07 13:30:56 +05:30
Matti Nannt
70cf58b55c Merge branch 'main' into piyush/enterprise-license-check 2024-05-06 18:00:45 +02:00
Anshuman Pandey
68fc25587c Merge branch 'main' into piyush/enterprise-license-check 2024-05-06 17:39:17 +05:30
pandeymangg
4c54c0d934 Merge branch 'main' into piyush/enterprise-license-check 2024-05-06 17:20:49 +05:30
pandeymangg
93b49969f9 fix: removes logs, refactor 2024-05-06 17:18:43 +05:30
pandeymangg
2839e49ccb testing 2024-05-06 16:52:57 +05:30
pandeymangg
e1dae1bd98 Merge branch 'main' into piyush/enterprise-license-check 2024-05-06 16:33:46 +05:30
pandeymangg
606305e54b Merge branch 'main' into piyush/enterprise-license-check 2024-05-03 15:55:45 +05:30
pandeymangg
0d1ded1139 Merge branch 'main' into piyush/enterprise-license-check 2024-05-03 14:06:20 +05:30
pandeymangg
6b1b2895f8 fix: feedback 2024-05-03 14:05:59 +05:30
pandeymangg
a3cb37b128 refactor 2024-05-02 15:06:07 +05:30
pandeymangg
b27314cec6 fix: caching for license key check 2024-05-02 15:03:58 +05:30
pandeymangg
1891f286e7 wip 2024-05-01 15:36:03 +05:30
pandeymangg
48409ced60 fix: short circuit logix 2024-05-01 11:41:36 +05:30
pandeymangg
9a7e5bfa8d Merge branch 'main' into piyush/enterprise-license-check 2024-05-01 11:36:23 +05:30
Piyush Gupta
adcba0139a Merge branch 'main' of https://github.com/formbricks/formbricks into piyush/enterprise-license-check 2024-04-16 09:53:19 +05:30
Piyush Gupta
0d3f7103af refactoring of getIsEnterpriseEdition service 2024-04-15 15:01:21 +05:30
Piyush Gupta
a51d68d23f Merge branch 'main' of https://github.com/formbricks/formbricks into piyush/enterprise-license-check 2024-04-15 09:09:21 +05:30
Piyush Gupta
0d33c27295 used unstable_cache instead of custom cache 2024-04-12 16:29:00 +05:30
Piyush Gupta
4fa4528771 adds enterprise license check 2024-04-12 15:02:07 +05:30
1633 changed files with 40056 additions and 51735 deletions

View File

@@ -22,7 +22,7 @@
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "cp .env.example .env && sed -i '/^ENCRYPTION_KEY=/c\\ENCRYPTION_KEY='$(openssl rand -hex 32) .env && sed -i '/^NEXTAUTH_SECRET=/c\\NEXTAUTH_SECRET='$(openssl rand -hex 32) .env && pnpm install && pnpm db:migrate:dev",
"postAttachCommand": "pnpm dev --filter=@formbricks/web... --filter=@formbricks/demo...",
"postAttachCommand": "pnpm dev --filter=web... --filter=demo...",
// Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "node"

View File

@@ -35,5 +35,3 @@ yarn-error.log*
.vscode
.github
**/.turbo
.env

View File

@@ -28,17 +28,13 @@ DATABASE_URL='postgresql://postgres:postgres@localhost:5432/formbricks?schema=pu
###############
# @see: https://next-auth.js.org/configuration/options#nextauth_secret
# You can use: `openssl rand -hex 32` to generate a secure one
# You can use: `openssl rand -hex 32` to generate one
NEXTAUTH_SECRET=RANDOM_STRING
# Set this to your public-facing URL, e.g., https://example.com
# You do not need the NEXTAUTH_URL environment variable in Vercel.
NEXTAUTH_URL=http://localhost:3000
# Cron Secret
# You can use: `openssl rand -hex 32` to generate a secure one
CRON_SECRET=
################
# MAIL SETUP #
################
@@ -87,13 +83,12 @@ EMAIL_VERIFICATION_DISABLED=1
PASSWORD_RESET_DISABLED=1
# Signup. Disable the ability for new users to create an account.
# Note: This variable is only available to the SaaS setup of Formbricks Cloud. Signup is disable by default for self-hosting.
# SIGNUP_DISABLED=1
# Email login. Disable the ability for users to login with email.
# EMAIL_AUTH_DISABLED=1
# Organization Invite. Disable the ability for invited users to create an account.
# Team Invite. Disable the ability for invited users to create an account.
# INVITE_DISABLED=1
##########
@@ -125,6 +120,9 @@ AZUREAD_TENANT_ID=
# OIDC_DISPLAY_NAME=
# OIDC_SIGNING_ALGORITHM=
# Cron Secret
CRON_SECRET=
# Configure this when you want to ship JS & CSS files from a complete URL instead of the current domain
# ASSET_PREFIX_URL=
@@ -156,11 +154,14 @@ SLACK_CLIENT_SECRET=
# Enterprise License Key
ENTERPRISE_LICENSE_KEY=
# Automatically assign new users to a specific organization and role within that organization
# Insert an existing organization id or generate a valid CUID for a new one at https://www.getuniqueid.com/cuid (e.g. cjld2cjxh0000qzrmn831i7rn)
# Automatically assign new users to a specific team and role within that team
# Insert an existing team id or generate a valid CUID for a new one at https://www.getuniqueid.com/cuid (e.g. cjld2cjxh0000qzrmn831i7rn)
# (Role Management is an Enterprise feature)
# DEFAULT_ORGANIZATION_ID=
# DEFAULT_ORGANIZATION_ROLE=admin
# DEFAULT_TEAM_ID=
# DEFAULT_TEAM_ROLE=admin
# set to 1 to skip onboarding for new users
# ONBOARDING_DISABLED=1
# Send new users to customer.io
# CUSTOMER_IO_API_KEY=

View File

@@ -1,2 +0,0 @@
node_modules/
packages/config-eslint/

10
.eslintrc.js Normal file
View File

@@ -0,0 +1,10 @@
module.exports = {
root: true,
// This tells ESLint to load the config from the package `eslint-config-formbricks`
extends: ["formbricks"],
settings: {
next: {
rootDir: ["apps/*/"],
},
},
};

View File

@@ -16,6 +16,9 @@ runs:
- uses: ./.github/actions/dangerous-git-checkout
- run: echo "E2E Testing Mode is ${{ inputs.e2e_testing_mode }}"
shell: bash
- name: Cache Build
uses: actions/cache@v3
id: cache-build
@@ -49,16 +52,20 @@ runs:
run: cp .env.example .env
shell: bash
- name: Fill ENCRYPTION_KE, ENTERPRISE_LICENSE_KEY and E2E_TESTING in .env
- name: Add E2E Testing Mode
run: |
RANDOM_KEY=$(openssl rand -hex 32)
sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=${RANDOM_KEY}/" .env
sed -i "s/ENTERPRISE_LICENSE_KEY=.*/ENTERPRISE_LICENSE_KEY=${RANDOM_KEY}/" .env
echo "E2E_TESTING=${{ inputs.e2e_testing_mode }}" >> .env
echo "E2E_TESTING=${{ inputs.e2e_testing_mode }}" >> $GITHUB_ENV
shell: bash
- name: Generate Random ENCRYPTION_KEY
run: |
SECRET=$(openssl rand -hex 32)
echo "ENCRYPTION_KEY=$SECRET" >> $GITHUB_ENV
echo "ENTERPRISE_LICENSE_KEY=$SECRET" >> $GITHUB_ENV
shell: bash
- run: |
pnpm build --filter=@formbricks/web...
pnpm build --filter=web...
if: steps.cache-build.outputs.cache-hit != 'true'
shell: bash

View File

@@ -0,0 +1,26 @@
name: Build formbricks-com
on:
workflow_call:
jobs:
build:
name: Build Formbricks-com
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repo
uses: actions/checkout@v3
- name: Setup Node.js 20.x
uses: actions/setup-node@v3
with:
node-version: 20.x
- name: Install pnpm
uses: pnpm/action-setup@v2
- name: Install dependencies
run: pnpm install --config.platform=linux --config.architecture=x64
- name: Build Formbricks-com
run: pnpm build --filter=formbricks-com...

View File

@@ -31,4 +31,4 @@ jobs:
echo "ENCRYPTION_KEY=$SECRET" >> $GITHUB_ENV
- name: Build Formbricks-web
run: pnpm build --filter=@formbricks/web...
run: pnpm build --filter=web...

View File

@@ -0,0 +1,24 @@
name: Cron - Report usage to Stripe
on:
workflow_dispatch:
# "Scheduled workflows run on the latest commit on the default or base branch."
# — https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule
# schedule:
# This will run the job at 20:00 UTC every day of every month.
# - cron: "0 20 * * *"
jobs:
cron-reportUsageToStripe:
env:
APP_URL: ${{ secrets.APP_URL }}
CRON_SECRET: ${{ secrets.CRON_SECRET }}
runs-on: ubuntu-latest
steps:
- name: cURL request
if: ${{ env.APP_URL && env.CRON_SECRET }}
run: |
curl ${{ env.APP_URL }}/api/cron/report-usage \
-X POST \
-H 'x-api-key: ${{ env.CRON_SECRET }}' \
-H 'Cache-Control: no-cache' \
--fail

View File

@@ -4,9 +4,9 @@ on:
workflow_dispatch:
# "Scheduled workflows run on the latest commit on the default or base branch."
# — https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#schedule
schedule:
# Runs “At 08:00 on Monday.” (see https://crontab.guru)
- cron: "0 8 * * 1"
# schedule:
# Runs “At 08:00 on Monday.” (see https://crontab.guru)
# - cron: "0 8 * * 1"
jobs:
cron-weeklySummary:
env:

View File

@@ -2,6 +2,9 @@ name: E2E Tests
on:
workflow_call:
workflow_dispatch:
push:
branches:
- action-test
jobs:
build:
name: Run E2E Tests
@@ -40,7 +43,7 @@ jobs:
- name: Run App
run: |
NODE_ENV=test pnpm start --filter=@formbricks/web &
NODE_ENV=test pnpm start --filter=web &
for attempt in {1..20}; do
if [ $(curl -o /dev/null -s -w "%{http_code}" http://localhost:3000/health) -eq 200 ]; then
echo "Ready"

View File

@@ -5,9 +5,9 @@ concurrency:
on:
workflow_dispatch:
#push:
# branches:
# - main
push:
branches:
- main
jobs:
Deploy:
@@ -56,7 +56,8 @@ jobs:
GOOGLE_SHEETS_REDIRECT_URL: ${{ secrets.GOOGLE_SHEETS_REDIRECT_URL }}
AIRTABLE_CLIENT_ID: ${{ secrets.AIRTABLE_CLIENT_ID }}
ENTERPRISE_LICENSE_KEY: ${{ secrets.ENTERPRISE_LICENSE_KEY }}
DEFAULT_ORGANIZATION_ID: ${{ vars.DEFAULT_ORGANIZATION_ID }}
DEFAULT_TEAM_ID: ${{ vars.DEFAULT_TEAM_ID }}
ONBOARDING_DISABLED: ${{ vars.ONBOARDING_DISABLED }}
CUSTOMER_IO_API_KEY: ${{ secrets.CUSTOMER_IO_API_KEY }}
CUSTOMER_IO_SITE_ID: ${{ secrets.CUSTOMER_IO_SITE_ID }}
NEXT_PUBLIC_POSTHOG_API_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_API_KEY }}

View File

@@ -53,7 +53,8 @@ jobs:
GOOGLE_SHEETS_REDIRECT_URL: ${{ secrets.GOOGLE_SHEETS_REDIRECT_URL }}
AIRTABLE_CLIENT_ID: ${{ secrets.AIRTABLE_CLIENT_ID }}
ENTERPRISE_LICENSE_KEY: ${{ secrets.ENTERPRISE_LICENSE_KEY }}
DEFAULT_ORGANIZATION_ID: ${{ vars.DEFAULT_ORGANIZATION_ID }}
DEFAULT_TEAM_ID: ${{ vars.DEFAULT_TEAM_ID }}
ONBOARDING_DISABLED: ${{ vars.ONBOARDING_DISABLED }}
CUSTOMER_IO_API_KEY: ${{ secrets.CUSTOMER_IO_API_KEY }}
CUSTOMER_IO_SITE_ID: ${{ secrets.CUSTOMER_IO_SITE_ID }}
NEXT_PUBLIC_POSTHOG_API_KEY: ${{ vars.NEXT_PUBLIC_POSTHOG_API_KEY }}

View File

@@ -25,10 +25,10 @@ jobs:
- name: create .env
run: cp .env.example .env
- name: Generate Random ENCRYPTION_KEY and fill in .env
- name: Generate Random ENCRYPTION_KEY
run: |
ENCRYPTION_KEY=$(openssl rand -hex 32)
sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=${ENCRYPTION_KEY}/" .env
SECRET=$(openssl rand -hex 32)
echo "ENCRYPTION_KEY=$SECRET" >> $GITHUB_ENV
- name: Lint
run: pnpm lint

View File

@@ -1,10 +1,9 @@
name: Release Changesets
on:
workflow_dispatch:
#push:
# branches:
# - main
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}

View File

@@ -33,7 +33,9 @@ jobs:
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@v3.5.0
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
with:
cosign-release: "v2.1.1"
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3

View File

@@ -1,91 +0,0 @@
name: Docker Release to Github Experimental
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on:
workflow_dispatch:
env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}-experimental
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
DATABASE_URL: "postgresql://postgres:postgres@localhost:5432/formbricks?schema=public"
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
# This is used to complete the identity challenge
# with sigstore/fulcio when running outside of PRs.
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Set up Depot CLI
uses: depot/setup-action@v1
# Install the cosign tool except on PR
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@v3.5.0
# Login against a Docker registry except on PR
# https://github.com/docker/login-action
- name: Log into registry ${{ env.REGISTRY }}
if: github.event_name != 'pull_request'
uses: docker/login-action@v3 # v3.0.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# Extract metadata (tags, labels) for Docker
# https://github.com/docker/metadata-action
- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@v5 # v5.0.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Build and push Docker image with Buildx (don't push on PR)
# https://github.com/docker/build-push-action
- name: Build and push Docker image
id: build-and-push
uses: depot/build-push-action@v1
with:
project: tw0fqmsx3c
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
context: .
file: ./apps/web/Dockerfile
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# Sign the resulting Docker image digest except on PRs.
# This will only write to the public Rekor transparency log when the Docker
# repository is public to avoid leaking data. If you would like to publish
# transparency data even for private images, pass --force to cosign below.
# https://github.com/sigstore/cosign
- name: Sign the published Docker image
if: ${{ github.event_name != 'pull_request' }}
env:
# https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable
TAGS: ${{ steps.meta.outputs.tags }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
# This step uses the identity token to provision an ephemeral certificate
# against the sigstore community Fulcio instance.
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}

View File

@@ -1,4 +1,4 @@
name: Docker Release to Github
name: Docker
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
@@ -41,7 +41,9 @@ jobs:
# https://github.com/sigstore/cosign-installer
- name: Install cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@v3.5.0
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 #v3.1.1
with:
cosign-release: "v2.1.1"
# Login against a Docker registry except on PR
# https://github.com/docker/login-action

View File

@@ -25,10 +25,10 @@ jobs:
- name: create .env
run: cp .env.example .env
- name: Generate Random ENCRYPTION_KEY and fill in .env
- name: Generate Random ENCRYPTION_KEY
run: |
ENCRYPTION_KEY=$(openssl rand -hex 32)
sed -i "s/ENCRYPTION_KEY=.*/ENCRYPTION_KEY=${ENCRYPTION_KEY}/" .env
SECRET=$(openssl rand -hex 32)
echo "ENCRYPTION_KEY=$SECRET" >> $GITHUB_ENV
- name: Test
run: pnpm test

View File

@@ -1,4 +1,4 @@
const baseConfig = require("./packages/config-prettier/prettier-preset");
const baseConfig = require("./packages/prettier-config/prettier-preset");
module.exports = {
...baseConfig,

View File

@@ -82,7 +82,7 @@ Formbricks is both a free and open source survey platform - and a privacy-first
- 🔗 Create shareable **link surveys**.
- 👨‍👩‍👦 Invite your organization members to **collaborate** on your surveys.
- 👨‍👩‍👦 Invite your team members to **collaborate** on your surveys.
- 🔌 Integrate Formbricks with **Slack, Notion, Zapier, n8n and more**.
@@ -224,7 +224,7 @@ Additional to the AGPL licensed Formbricks core, this repository contains code l
### White-Labeling Formbricks and Other Licensing Needs
We currently do not offer Formbricks white-labeled. Any other needs? [Send us an email](mailto:hola@formbricks.com).
If you have other licensing requirements such as White-Labeling please [send us an email](mailto:hola@formbricks.com).
### Why charge for Enterprise Features?

View File

@@ -1,3 +1,4 @@
module.exports = {
extends: ["@formbricks/eslint-config/legacy-next.js"],
root: true,
extends: ["formbricks"],
};

View File

@@ -1,6 +1,6 @@
import { Sidebar } from "./Sidebar";
import Sidebar from "./Sidebar";
export const LayoutApp = ({ children }: { children: React.ReactNode }) => {
export default function LayoutApp({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-full">
{/* Static sidebar for desktop */}
@@ -10,4 +10,4 @@ export const LayoutApp = ({ children }: { children: React.ReactNode }) => {
<div className="flex flex-1 flex-col lg:pl-64">{children}</div>
</div>
);
};
}

View File

@@ -9,6 +9,7 @@ import {
ShieldCheckIcon,
UsersIcon,
} from "lucide-react";
import { classNames } from "../lib/utils";
const navigation = [
@@ -25,7 +26,7 @@ const secondaryNavigation = [
{ name: "Privacy", href: "#", icon: ShieldCheckIcon },
];
export const Sidebar = () => {
export default function Sidebar({}) {
return (
<div className="flex flex-grow flex-col overflow-y-auto bg-cyan-700 pb-4 pt-5">
<nav
@@ -62,4 +63,4 @@ export const Sidebar = () => {
</nav>
</div>
);
};
}

View File

@@ -1,3 +1,5 @@
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@formbricks/ui/Select";
interface SurveySwitchProps {
value: "website" | "app";
formbricks: any;
@@ -5,18 +7,19 @@ interface SurveySwitchProps {
export const SurveySwitch = ({ value, formbricks }: SurveySwitchProps) => {
return (
<select
<Select
value={value}
onChange={(v) => {
onValueChange={(v) => {
formbricks.logout();
window.location.href = `/${v.target.value}`;
window.location.href = `/${v}`;
}}>
<option value="website" className="h-10 px-4 hover:bg-slate-100">
Website Surveys
</option>
<option value="app" className="hover:bg-slate-10 h-10 px-4">
App Surveys
</option>
</select>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
<SelectItem value="website">Website Surveys</SelectItem>
<SelectItem value="app">App Surveys</SelectItem>
</SelectContent>
</Select>
);
};

View File

@@ -1,3 +1,3 @@
export const classNames = (...classes: any) => {
export function classNames(...classes: any) {
return classes.filter(Boolean).join(" ");
};
}

View File

@@ -1,6 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
transpilePackages: ["@formbricks/ui"],
async redirects() {
return [
{
@@ -24,4 +25,4 @@ const nextConfig = {
},
};
export default nextConfig;
module.exports = nextConfig;

View File

@@ -13,13 +13,13 @@
"dependencies": {
"@formbricks/js": "workspace:*",
"@formbricks/ui": "workspace:*",
"lucide-react": "^0.395.0",
"next": "14.2.4",
"react": "18.3.1",
"react-dom": "18.3.1"
"lucide-react": "^0.373.0",
"next": "14.2.3",
"react": "18.2.0",
"react-dom": "18.2.0"
},
"devDependencies": {
"@formbricks/eslint-config": "workspace:*",
"@formbricks/config-typescript": "workspace:*"
"eslint-config-formbricks": "workspace:*",
"@formbricks/tsconfig": "workspace:*"
}
}

View File

@@ -1,8 +1,9 @@
import type { AppProps } from "next/app";
import Head from "next/head";
import "../styles/globals.css";
const App = ({ Component, pageProps }: AppProps) => {
export default function App({ Component, pageProps }: AppProps) {
return (
<>
<Head>
@@ -17,6 +18,4 @@ const App = ({ Component, pageProps }: AppProps) => {
<Component {...pageProps} />
</>
);
};
export default App;
}

View File

@@ -1,6 +1,6 @@
import { Head, Html, Main, NextScript } from "next/document";
const Document = () => {
export default function Document() {
return (
<Html lang="en" className="h-full bg-slate-50">
<Head />
@@ -10,6 +10,4 @@ const Document = () => {
</body>
</Html>
);
};
export default Document;
}

View File

@@ -1,13 +1,15 @@
import Image from "next/image";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import formbricks from "@formbricks/js/app";
import { SurveySwitch } from "../../components/SurveySwitch";
import fbsetup from "../../public/fb-setup.png";
declare const window: any;
const AppPage = ({}) => {
export default function AppPage({}) {
const [darkMode, setDarkMode] = useState(false);
const router = useRouter();
@@ -34,11 +36,7 @@ const AppPage = ({}) => {
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const userId = "THIS-IS-A-VERY-LONG-USER-ID-FOR-TESTING";
const userInitAttributes = {
language: "de",
"Init Attribute 1": "eight",
"Init Attribute 2": "two",
};
const userInitAttributes = { language: "de", "Init Attribute 1": "eight", "Init Attribute 2": "two" };
formbricks.init({
environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID,
@@ -57,7 +55,7 @@ const AppPage = ({}) => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}
}, []);
});
return (
<div className="h-screen bg-white px-12 py-6 dark:bg-slate-800">
@@ -117,7 +115,7 @@ const AppPage = ({}) => {
</div>
<div className="md:grid md:grid-cols-3">
<div className="col-span-3 self-start rounded-lg border border-slate-300 bg-slate-100 p-6 dark:border-slate-600 dark:bg-slate-800">
<div className="col-span-3 rounded-lg border border-slate-300 bg-slate-100 p-6 dark:border-slate-600 dark:bg-slate-800">
<h3 className="text-lg font-semibold dark:text-white">
Reset person / pull data from Formbricks app
</h3>
@@ -138,6 +136,26 @@ const AppPage = ({}) => {
</p>
</div>
<div className="p-6">
<div>
<button
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600"
onClick={() => {
formbricks.track("Code Action");
}}>
Code Action
</button>
</div>
<div>
<p className="text-xs text-slate-700 dark:text-slate-300">
This button sends a{" "}
<a href="https://formbricks.com/docs/actions/code" className="underline" target="_blank">
Code Action
</a>{" "}
to the Formbricks API called &apos;Code Action&apos;. You will find it in the Actions Tab.
</p>
</div>
</div>
<div className="p-6">
<div>
<button className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600">
@@ -236,6 +254,4 @@ const AppPage = ({}) => {
</div>
</div>
);
};
export default AppPage;
}

View File

@@ -1,13 +1,15 @@
import Image from "next/image";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import formbricks from "@formbricks/js/website";
import { SurveySwitch } from "../../components/SurveySwitch";
import fbsetup from "../../public/fb-setup.png";
declare const window: any;
const AppPage = ({}) => {
export default function AppPage({}) {
const [darkMode, setDarkMode] = useState(false);
const router = useRouter();
@@ -34,7 +36,7 @@ const AppPage = ({}) => {
if (process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID && process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST) {
const defaultAttributes = {
language: "en",
language: "de",
};
formbricks.init({
@@ -113,7 +115,7 @@ const AppPage = ({}) => {
</div>
<div className="md:grid md:grid-cols-3">
<div className="col-span-3 self-start rounded-lg border border-slate-300 bg-slate-100 p-6 dark:border-slate-600 dark:bg-slate-800">
<div className="col-span-3 rounded-lg border border-slate-300 bg-slate-100 p-6 dark:border-slate-600 dark:bg-slate-800">
<h3 className="text-lg font-semibold dark:text-white">
Reset person / pull data from Formbricks app
</h3>
@@ -133,10 +135,62 @@ const AppPage = ({}) => {
try again.
</p>
</div>
<div className="pt-6">
<div>
<button
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600"
onClick={() => {
formbricks.track("New Session");
}}>
Track New Session
</button>
</div>
<div>
<p className="text-xs text-slate-700 dark:text-slate-300">
This button sends an Action to the Formbricks API called &apos;New Session&apos;. You will
find it in the Actions Tab.
</p>
</div>
</div>
<div className="pt-6">
<div>
<button
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600"
onClick={() => {
formbricks.track("Exit Intent");
}}>
Track Exit Intent
</button>
</div>
<div>
<p className="text-xs text-slate-700 dark:text-slate-300">
This button sends an Action to the Formbricks API called &apos;Exit Intent&apos;. You can also
move your mouse to the top of the browser to trigger the exit intent.
</p>
</div>
</div>
<div className="pt-6">
<div>
<button
className="mb-4 rounded-lg bg-slate-800 px-6 py-3 text-white hover:bg-slate-700 dark:bg-slate-700 dark:hover:bg-slate-600"
onClick={() => {
formbricks.track("50% Scroll");
}}>
Track 50% Scroll
</button>
</div>
<div>
<p className="text-xs text-slate-700 dark:text-slate-300">
This button sends an Action to the Formbricks API called &apos;50% Scroll&apos;. You can also
scroll down to trigger the 50% scroll.
</p>
</div>
</div>
</div>
</div>
</div>
);
};
export default AppPage;
}

View File

@@ -1,5 +1,5 @@
{
"extends": "@formbricks/config-typescript/nextjs.json",
"extends": "@formbricks/tsconfig/nextjs.json",
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}

View File

@@ -1,3 +1,4 @@
module.exports = {
extends: ["@formbricks/eslint-config/legacy-next.js"],
root: true,
extends: ["formbricks"],
};

View File

@@ -35,4 +35,3 @@ yarn-error.log*
next-env.d.ts
public/sitemap*.xml
public/robots.txt

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -1,12 +1,12 @@
import { MdxImage } from "@/components/MdxImage";
import I1 from "./images/I1.webp";
import I2 from "./images/I2.webp";
import I1 from "./images/I1.png";
import I2 from "./images/I2.png";
export const metadata = {
title: "Using Actions in Formbricks | Fine-tuning User Moments",
description:
"Dive deep into how actions in Formbricks help products and organizations to engage users at precise moments in their journey. Discover the power of actions, from coding to no-code setups, to refine user targeting and generate richer, more detailed user insights.",
"Dive deep into how actions in Formbricks help products and teams to engage users at precise moments in their journey. Discover the power of actions, from coding to no-code setups, to refine user targeting and generate richer, more detailed user insights.",
};
#### App Surveys
@@ -22,7 +22,7 @@ Understanding user thoughts and feelings at critical moments in their journey is
## **How Do Actions Work?**
Actions in Formbricks App Surveys are deeply integrated with user activities within your app. When a user performs a specified action, the Formbricks widget detects this activity and can present a survey to that specific user if the trigger conditions match of that survey, while also recording the event. This capability ensures that surveys are not only triggered at the right time but are also tailored to the users recent interactions within the app. You can set up these actions through a user-friendly No-Code interface within the Formbricks dashboard.
Actions in Formbricks App Surveys are deeply integrated with user activities within your app. When a user performs a specified action, the Formbricks widget detects this activity and can present a survey to that specific user if the trigger conditions match of that survey, while also recording the event. This capability ensures that surveys are not only triggered at the right time but are also tailored to the users recent interactions within the app. You can set up these actions either programmatically in your code or through a user-friendly No-Code interface within the Formbricks dashboard.
## **Why Are Actions Useful?**
@@ -33,6 +33,13 @@ Actions are invaluable for enhancing survey relevance and effectiveness:
- **User Segments**: Analyze action data to create detailed user segments, targeting specific groups with surveys that are pertinent to their behaviors or interactions within the app.
- **User Targeting**: Precise targeting based on user actions and attributes ensures that surveys are shown only to users who meet certain criteria, enhancing the relevance and effectiveness of each survey.
<Note>
You now have the option to create survey-specific action classes directly within the survey editor. These
actions are exclusive to the individual survey and won't appear in the global action list, helping to keep
it uncluttered. For actions that are needed across multiple surveys, we recommend creating them from the
Actions tab.
</Note>
## **Setting Up No-Code Actions**
Formbricks offers an intuitive No-Code interface that allows you to configure actions without needing to write any code.
@@ -57,35 +64,12 @@ To add a No-Code Action:
className="max-w-full rounded-lg sm:max-w-3xl"
/>
Here are four types of No-Code actions you can set up:
Here are three types of No-Code actions you can set up:
### **1. Click Action**
Click Action is triggered when a user clicks on a specific element within your application. You can define the element's inner text or CSS selector to trigger the survey.
- **Inner Text**: Checks if the innerText of a clicked HTML element, like a button label, matches a specific text. This action allows you to display a survey based on text interactions within your application.
- **CSS Selector**: Verifies if a clicked HTML element matches a provided CSS selector, such as a class, ID, or any other CSS selector used in your website. It enables survey triggers based on element interactions.
### **2. Page view Action**
This action is triggered when a user visits a page within your application.
### **3. Exit Intent Action**
This action is triggered when a user is about to leave your application. It helps capture user feedback before they exit, providing valuable insights into user experiences and potential improvements.
### **4. 50% Scroll Action**
This action is triggered when a user scrolls through 50% of a page within your application. It helps capture user feedback at a specific point in their journey, enabling you to gather insights based on user interactions.
### **1. Page URL Action**
This action is triggered when a user visits a specific page within your application. You can define the URL match conditions as follows:
<Note>
You can combine the url filters with any of the no-code actions to trigger the survey based on the URL match conditions.
### **URL Match Conditions**
- **exactMatch**: Triggers the action when the URL exactly matches the specified string.
- **contains**: Activates when the URL contains the specified substring.
- **startsWith**: Fires when the URL starts with the specified string.
@@ -93,7 +77,15 @@ You can combine the url filters with any of the no-code actions to trigger the s
- **notMatch**: Triggers when the URL does not match the specified condition.
- **notContains**: Activates when the URL does not contain the specified substring.
</Note>
### **2. innerText Action**
Checks if the innerText of a clicked HTML element, like a button label, matches a specific text. This action allows you to display a survey based on text interactions within your application.
### **3. CSS Selector Action**
This action verifies if a clicked HTML element matches a provided CSS selector, such as a class, ID, or any other CSS selector used in your website. It enables survey triggers based on element interactions.
<Note>You can have an action use combination of the 3 types as you wish</Note>
## **Setting Up Code Actions**

View File

@@ -1,5 +1,4 @@
import { MdxImage } from "@/components/MdxImage";
import { ResponsiveVideo } from "@/components/ResponsiveVideo";
import GermansGpt from "./germans-gpt.webp";
import Hni from "./hni.webp";
@@ -19,9 +18,13 @@ export const metadata = {
Advanced Targeting allows you to show surveys to the right group of people. You can target surveys based on user attributes, user events, and more instead of spraying and praying. This helps you get more relevant feedback and make data-driven decisions. All of this without writing a single line of code.
<ResponsiveVideo title="Formbricks Multi-language Surveys"
src="https://www.youtube-nocookie.com/embed/0BQp6N4cXzU?si=KeBM7G7Ch1xtrsOm&amp;controls=0" />
<iframe
width="700"
height="450"
src="https://www.youtube.com/embed/0BQp6N4cXzU?si=gyeEZRXZ6Kei1zzm"
title="YouTube video player: Formbricks"
frameborder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"></iframe>
## How to setup Advanced Targeting

View File

@@ -33,7 +33,7 @@ const libraries = [
},
];
export const Libraries = () => {
export function Libraries() {
return (
<div className="my-16 xl:max-w-none">
<div className="not-prose mt-4 grid grid-cols-1 gap-x-6 gap-y-10 border-slate-900/5 sm:grid-cols-2 xl:max-w-none xl:grid-cols-3 dark:border-white/5">
@@ -57,4 +57,4 @@ export const Libraries = () => {
</div>
</div>
);
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -2,6 +2,7 @@ import { MdxImage } from "@/components/MdxImage";
import { Libraries } from "./components/Libraries";
import SetupChecklist from "./images/env-id.png";
import ReactApp from "./images/react-in-app-survey-app-popup-form.webp";
import WidgetConnected from "./images/widget-connected.webp";
import WidgetNotConnected from "./images/widget-not-connected.webp";
@@ -26,7 +27,14 @@ for something else, please [join our Discord!](https://formbricks.com/discord) a
Before getting started, make sure you have:
1. A web application (behind your user authentication system) in your desired framework is set up and running.
2. A Formbricks account with access to your environment ID and API host. You can find these in the **Setup Checklist** in the Settings.
2. A Formbricks account with access to your environment ID and API host. You can find these in the **Setup Checklist** in the Settings:
<MdxImage
src={SetupChecklist}
alt="Step 2 - Setup Checklist"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
---

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -1,13 +1,14 @@
import { MdxImage } from "@/components/MdxImage";
import I1 from "./images/I1.webp";
import I2 from "./images/I2.webp";
import I3 from "./images/I3.webp";
import I4 from "./images/I4.webp";
import I5 from "./images/I5.webp";
import I6 from "./images/I6.webp";
import I7 from "./images/I7.webp";
import I8 from "./images/I8.webp";
import I1 from "./images/I1.png";
import I2 from "./images/I2.png";
import I3 from "./images/I3.png";
import I4 from "./images/I4.png";
import I5 from "./images/I5.png";
import I6 from "./images/I6.png";
import I7 from "./images/I7.png";
import I8 from "./images/I8.png";
export const metadata = {
title: "Formbricks Quickstart Guide: App Surveys Made Easier & Faster",
@@ -16,19 +17,18 @@ export const metadata = {
};
#### App Surveys
# Quickstart
App surveys have 6-10x better conversion rates than emailed out surveys. This tutorial explains how to run an app survey in your web app in 10 to 15 minutes. Lets go!
<Note>
App Surveys are ideal for websites that **have a user authentication** system. If you are looking to run surveys on your public facing website, head over to the [Website Surveys Quickstart Guide](/website-surveys/quickstart).
App Surveys are ideal for websites that **have a user authentication** system. If you are looking to run surveys on your public facing website, head over to the [Website Surveys Quickstart Guide](/website-surveys/quickstart).
</Note>
1. **Create a free Formbricks Cloud account**: While you can [self-host](/self-hosting/deployment) Formbricks, but the quickest and easiest way to get started is with the free Cloud plan. Just [sign up here](https://app.formbricks.com/auth/signup) and you'll be guided to our onboarding like below:
<Note>
Website & App Surveys have the same integration process. The difference will come when we setup our survey.
Website & App Surveys have the same integration process. The difference will come when we setup our survey.
</Note>
<MdxImage
@@ -70,41 +70,41 @@ Onboarding is complete! Now lets create our first survey as you should see te
Pick the Survey Type as **App Survey**.
<MdxImage
src={I5}
alt="Survey settings for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
src={I5}
alt="Survey settings for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
4. **Set Trigger for the Survey**: Scroll down to Survey Trigger and click on **+ Add action**, choose **New Session**. This will cause this survey to appear when the Formbricks Widget tracks a new user session:
4. **Set Trigger for the Survey**: Scroll down to Survey Trigger and inside **When**, choose **New Session**. This will cause this survey to appear when the Formbricks Widget tracks a new user session:
<MdxImage
src={I6}
alt="Survey trigger settings for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
src={I6}
alt="Survey trigger settings for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
5. **Set Recontact Options for debugging**: In Recontact Options we choose the following settings, so that we can play around with the survey more easily. By default, each survey will be shown only once to each user to prevent survey fatigue:
<Note>
Please change this setting later on after testing your survey to prevent survey fatigue for your users.
Please change this setting later on after testing your survey to prevent survey fatigue for your users.
</Note>
<MdxImage
src={I7}
alt="Recontact options for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
src={I7}
alt="Recontact options for app survey"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
6. **Publish your survey**: Now hit **Publish** and youll be forwarded to the Summary Page. This is where youll find the responses to this survey.
<MdxImage
src={I8}
alt="Survey published successfully"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
src={I8}
alt="Survey published successfully"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
---

View File

@@ -80,11 +80,6 @@ formbricks.init({
You can use the setAttribute function to set any custom attribute for the user (e.g. name, plan, etc.):
<Note>
Please note that the number of different attribute classes (e.g., "Plan," "First Name," etc.) is currently
limited to 150 attributes per environment.
</Note>
<Col>
<CodeGroup title="Setting Custom Attributes">
@@ -120,4 +115,4 @@ formbricks.logout();
```
</CodeGroup>
</Col>
</Col>

View File

@@ -41,7 +41,9 @@ To run the Churn Survey in your app you want to proceed as follows:
4. Prevent that churn!
<Note>
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (takes 15mins max.)](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(takes 15mins max.)](/app-surveys/quickstart)
</Note>
### 1. Create new Churn Survey
@@ -78,9 +80,9 @@ In this case, you dont really need to pre-segment your audience. You likely w
### 4. Set up a trigger
To create the trigger for your Churn Survey, you have three options to choose from:
To create the trigger for your Churn Survey, you have two options to choose from:
1. **Trigger by Inner Text:** You likely have a “Cancel Subscription” button in your app. You can setup a user Action with the according `Inner Text` to trigger the survey, like so:
1. **Trigger by innerText:** You likely have a “Cancel Subscription” button in your app. You can setup a user Action with the according `innerText` to trigger the survey, like so:
<MdxImage
src={TriggerInnerText}
@@ -98,7 +100,7 @@ To create the trigger for your Churn Survey, you have three options to choose fr
className="max-w-full rounded-lg sm:max-w-3xl"
/>
1. **Trigger by page view filters:** Lastly, you could also display your survey on a subpage “/subscription-cancelled” where you forward users once they cancelled the trial subscription. You can then create a user Action with the type `Page View` and add select `Limit to specific pages` to add url filters, with the following settings:
3. **Trigger by pageURL:** Lastly, you could also display your survey on a subpage “/subscription-cancelled” where you forward users once they cancelled the trial subscription. You can then create a user Action with the type `pageURL` with the following settings:
<MdxImage
src={TriggerPageUrl}
@@ -109,7 +111,7 @@ To create the trigger for your Churn Survey, you have three options to choose fr
Whenever a user visits this page, matches the filter conditions above and the recontact options (below) the survey will be displayed ✅
Here is our complete [Actions manual](/app-surveys/actions/) covering [No-Code](/app-surveys/actions#setting-up-no-code-actions) and [Code](/app-surveys/actions#setting-up-code-actions) Actions.
Here is our complete [Actions manual](/actions/why) covering [Code](/actions/code) and [No-Code](/actions/no-code) Actions.
<Note>
## Pre-churn flow coming soon Were currently building full-screen survey pop-ups. Youll be able to prevent
@@ -150,7 +152,8 @@ These settings make sure the survey is always displayed, when a user wants to Ca
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Churn Survey
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
###

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -5,9 +5,9 @@ import ChangeId from "./change-id.webp";
import CopyIds from "./copy-ids.webp";
import DocsNavi from "./docs-navi.webp";
import DocsTemplate from "./docs-template.webp";
import SelectAction from "./select-action.webp";
import SurveyTrigger from "./survey-trigger.webp";
import SelectNonevent from "./select-nonevent.webp";
import SwitchToDev from "./switch-to-dev.webp";
import WhenToAsk from "./when-to-ask.webp";
export const metadata = {
title:
@@ -73,10 +73,10 @@ To get this running, you'll need a bit of time. Here are the steps we're going t
choices accordingly. They have to be identical to the frontend we're building in the next step.
</Note>
6. Click on “Continue to Settings or select the audience tab manually. Scroll down to “Survey Trigger” and create a new Action:
6. Click on “Continue to Settings or select the audience tab manually. Scroll down to “When to ask” and create a new Action:
<MdxImage
src={SurveyTrigger}
src={WhenToAsk}
alt="set up when to ask card"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
@@ -89,7 +89,7 @@ To get this running, you'll need a bit of time. Here are the steps we're going t
8. Select the Non-Event in the dropdown. Now you see that the “Publish survey” button is active. Publish your survey 🤝
<MdxImage
src={SelectAction}
src={SelectNonevent}
alt="select nonevent"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
@@ -135,7 +135,7 @@ import { Popover, PopoverContent, PopoverTrigger } from "@formbricks/ui/Popover"
import { handleFeedbackSubmit, updateFeedback } from "../../lib/handleFeedbackSubmit";
export const DocsFeedback = () => {
export default function DocsFeedback() {
const router = useRouter();
const [isOpen, setIsOpen] = useState(false);
const [sharedFeedback, setSharedFeedback] = useState(false);
@@ -199,7 +199,7 @@ export const DocsFeedback = () => {
)}
</div>
);
};
}
```
</CodeGroup>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,7 +1,7 @@
import { MdxImage } from "@/components/MdxImage";
import ActionCSS from "./action-css.webp";
import ActionText from "./action-innertext.webp";
import ActionText from "./action-text.webp";
import ChangeText from "./change-text.webp";
import CreateSurvey from "./create-survey.webp";
import Publish from "./publish.webp";
@@ -38,10 +38,9 @@ To run the Feature Chaser survey in your app you want to proceed as follows:
2. Setup a user action to display survey at the right point in time
<Note>
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web
wapp. Its required to display messages and surveys in your app. If not, please follow the [Quick Start
Guide (takes 15mins max.)](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(takes 15mins max.)](/app-surveys/quickstart)
</Note>
### 1. Create new Feature Chaser
@@ -74,11 +73,11 @@ Save, and move over to where the magic happens: The “Audience” tab.
Before setting the right trigger, you need to identify a user action in your app which signals, that they have just used the feature you want to understand better. In most cases, it is clicking a specific button in your product.
You can create [Code Actions](/app-surveys/actions#setting-up-code-actions) and [No Code Actions](/app-surveys/actions#setting-up-no-code-actions) to follow users through your app. In this example, we will create a No Code Action.
You can create [Code Actions](/actions/code) and [No Code Actions](/actions/no-code) to follow users through your app. In this example, we will create a No Code Action.
There are two ways to track a button:
1. **Trigger by Inner Text:** You might have a button with a unique text at the end of your feature e.g. "Export Report". You can setup a user Action with the according `Inner Text` to trigger the survey, like so:
1. **Trigger by innerText:** You might have a button with a unique text at the end of your feature e.g. "Export Report". You can setup a user Action with the according `innerText` to trigger the survey, like so:
<MdxImage
src={ActionText}
@@ -124,7 +123,8 @@ Lastly, scroll down to “Recontact Options”. Here you have full freedom to de
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feature Chaser
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
###

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,13 +1,13 @@
import { MdxImage } from "@/components/MdxImage";
import Link from "next/link";
import ActionCSS from "./action-css.webp";
import ActionText from "./action-innertext.webp";
import AddAction from "./add-action.webp";
import AddCSSAction from "./add-css-action.webp";
import AddHTMLAction from "./add-html-action.webp";
import ChangeTextContent from "./change-text-content.webp";
import CreateFeedbackBox from "./create-feedback-box-by-template.webp";
import PublishSurvey from "./publish-survey.webp";
import SelectAction from "./select-action.webp";
import SelectAction from "./select-feedback-button-action.webp";
import RecontactOptions from "./set-recontact-options.webp";
export const metadata = {
@@ -65,18 +65,25 @@ Change the questions and answer options according to your preference:
### 3. Create user action to trigger Feedback Box:
Go to the “Audience” tab, find the “When to send” card and choose “Add Action”. We will now use our super cool User Action Tracker:
Go to the “Audience” tab, find the “When to send” card and choose “Add Action”. We will now use our super cool No-Code User Action Tracker:
<MdxImage src={AddAction} alt="Add action" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## You can also add actions in your code You can also create [Code Actions](/actions/code) using
`formbricks.track("Eventname")` - they will automatically appear in your Actions overview as long as the SDK
is embedded.
</Note>
We have two options to track the Feedback Button in your application: innerText and CSS-Selector:
1. **Inner Text:** This means that whenever a user clicks any HTML item in your app which has an `Inner Text` of `Feedback` the Feedback Box will be displayed.
1. **innerText:** This means that whenever a user clicks any HTML item in your app which has an `innerText` of `Feedback` the Feedback Box will be displayed.
2. **CSS-Selector:** This means that when an element with a specific CSS-Selector like `#feedback-button` is clicked, your Feedback Box is triggered.
<MdxImage src={ActionText} alt="Add HTML action" quality="100" className="rounded-lg" />
2. **CSS Selector:** This means that when an element with a specific CSS-Selector like `#feedback-button` is clicked, your Feedback Box is triggered.
<MdxImage src={ActionCSS} alt="Add CSS action" quality="100" className="rounded-lg" />
<div className="grid max-w-full grid-cols-2 space-x-2 sm:max-w-3xl">
<MdxImage src={AddHTMLAction} alt="Add HTML action" quality="100" className="rounded-lg" />
<MdxImage src={AddCSSAction} alt="Add CSS action" quality="100" className="rounded-lg" />
</div>
### 4. Select action in the “When to ask” card
@@ -111,7 +118,8 @@ Scroll down to “Recontact Options”. Here you have to choose the right settin
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
### &nbsp;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -38,8 +38,9 @@ To display the Trial Conversion Survey in your app you want to proceed as follow
3. Print that 💸
<Note>
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (takes 15mins max.)](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(takes 15mins max.)](/app-surveys/quickstart)
</Note>
### 1. Create new Trial Conversion Survey
@@ -83,7 +84,7 @@ Pre-segmentation isn't relevant for this survey because you likely want to solve
How you trigger your survey depends on your product. There are two options:
1. **Trigger by Page view:** Lets say you have a page under “/trial-cancelled” where you forward users once they cancelled the trial subscription. You can then create an user Action with the type `Page View` and add select `Limit to specific pages` to add url filters, with the following settings:
1. **Trigger by pageURL:** Lets say you have a page under “/trial-cancelled” where you forward users once they cancelled the trial subscription. You can then create an user Action with the type `pageURL` with the following settings:
<MdxImage
src={ActionPageurl}
@@ -94,7 +95,7 @@ How you trigger your survey depends on your product. There are two options:
Whenever a user visits this page, the survey will be displayed ✅
2. **Trigger by Button Click:** In a different case, you have a “Cancel Trial" button in your app. You can setup a user Action with the according `Inner Text` like so:
2. **Trigger by Button Click:** In a different case, you have a “Cancel Trial button in your app. You can setup a user Action with the according `innerText` like so:
<MdxImage
src={ActionText}
@@ -103,7 +104,7 @@ Whenever a user visits this page, the survey will be displayed ✅
className="max-w-full rounded-lg sm:max-w-3xl"
/>
Please have a look at our complete [Actions manual](/app-surveys/actions/) if you have questions.
Please have a look at our complete [Actions manual](/actions/why) if you have questions.
### 5. Select Action in the “When to ask” card
@@ -131,7 +132,8 @@ Lastly, scroll down to “Recontact Options”. Here you have to choose the corr
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
###

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@@ -43,8 +43,9 @@ To display an Interview Prompt in your app you want to proceed as follows:
3. Thats it! 🎉
<Note>
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (15mins).](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(15mins).](/app-surveys/quickstart)
</Note>
### 1. Create new Interview Prompt
@@ -85,7 +86,8 @@ Save, and move over to the “Audience” tab.
### 3. Pre-segment your audience (coming soon)
<Note>
## Filter by attribute coming soon. We're working on pre-segmenting users by attributes. We will update this manual in the next few days.
## Filter by attribute coming soon We're working on pre-segmenting users by attributes. We will update this
manual in the next few days.
</Note>
Once you clicked over to the “Audience” tab you can change the settings. In the **Who To Send** card, select “Filter audience by attribute”. This allows you to only show the prompt to a specific segment of your user base.
@@ -96,13 +98,19 @@ Great, now only the “Power User” segment will see our Interview Prompt. But
### 4. Set up a trigger for the Interview Prompt:
To create the trigger to show your Interview Prompt, go to the “Audience” tab, find the “When to send” card and choose “Add Action”. We will now use our super cool User Action Tracker:
To create the trigger to show your Interview Prompt, go to the “Audience” tab, find the “When to send” card and choose “Add Action”. We will now use our super cool No-Code User Action Tracker:
<MdxImage src={AddAction} alt="Add action" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## You can also add actions in your code You can also create [Code Actions](/actions/code) using
`formbricks.track("Eventname")` - they will automatically appear in your Actions overview as long as the SDK
is embedded.
</Note>
Generally, we have two types of user actions: Page views and clicks. The Interview Prompt, youll likely want to display it on a page visit since you already filter who sees the prompt by attributes.
1. **Page view:** Whenever a user visits a page the survey will be displayed, as long as the other conditions match. Other conditions are pre-segmentation, if this user has seen a survey in the past 2 weeks, etc.
1. **pageURL:** Whenever a user visits a page the survey will be displayed, as long as the other conditions match. Other conditions are pre-segmentation, if this user has seen a survey in the past 2 weeks, etc.
<MdxImage
src={ActionPageurl}
@@ -111,11 +119,21 @@ Generally, we have two types of user actions: Page views and clicks. The Intervi
className="max-w-full rounded-lg sm:max-w-3xl"
/>
2. **Click(Inner Text & CSS Selector):** When a user clicks an element (like a button) with a specific text content or CSS selector, the prompt will be displayed as long as the other conditions also match.
2. **innerText & CSS-Selector:** When a user clicks an element (like a button) with a specific text content or CSS selector, the prompt will be displayed as long as the other conditions also match.
<div className="grid max-w-full grid-cols-2 space-x-2 sm:max-w-3xl">
<MdxImage src={ActionCSS} alt="Add CSS action" quality="100" className="rounded-lg" />
<MdxImage src={ActionInner} alt="Add inner text action" quality="100" className="rounded-lg" />
<div className="flex max-w-full flex-col sm:max-w-3xl lg:gap-1">
<MdxImage
src={ActionCSS}
alt="Add CSS action"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
<MdxImage
src={ActionInner}
alt="Add inner text action"
quality="100"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
</div>
### 5. Select action in the “When to ask” card
@@ -143,7 +161,9 @@ Scroll down to “Recontact Options”. Here you have to choose the correct sett
<MdxImage src={Publish} alt="Publish survey" quality="100" className="max-w-full rounded-lg sm:max-w-3xl" />
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
###

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -37,8 +37,9 @@ To display the Product-Market Fit survey in your app you want to proceed as foll
3. Setup the user action to display survey at good point in time
<Note>
## Formbricks Widget running?
We assume that you have already installed the Formbricks Widget in your web app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide (15mins).](/app-surveys/quickstart)
## Formbricks Widget running? We assume that you have already installed the Formbricks Widget in your web
app. Its required to display messages and surveys in your app. If not, please follow the [Quick Start Guide
(15mins).](/app-surveys/quickstart)
</Note>
### 1. Create new PMF survey
@@ -84,28 +85,27 @@ To run this survey properly, you should pre-segment your user base. As touched u
- Check the time passed since sign-up (e.g. signed up 4 weeks ago)
- User has performed a specific action a certain number of times or (e.g. created 5 reports)
- User has performed a combination of actions (e.g. created a report **and** invited a organization member)
- User has performed a combination of actions (e.g. created a report **and** invited a team member)
This way you make sure that you separate potentially misleading opinions from valuable insights.
### 4. Set up a trigger for the Product-Market Fit survey:
You need a trigger to display the survey but in this case, the filtering does all the work. Its up to you to decide to display the survey after the user viewed a specific subpage (pageURL) or after clicking an element. Have a look at the [Actions manual](/app-surveys/actions/) if you are not sure how to set them up:
You need a trigger to display the survey but in this case, the filtering does all the work. Its up to you to decide to display the survey after the user viewed a specific subpage (pageURL) or after clicking an element. Have a look at the [Actions manual](/actions/why) if you are not sure how to set them up:
<Col>
<div className="grid max-w-full grid-cols-2 space-x-2 sm:max-w-3xl items-end">
<div>
<MdxImage
src={ActionCSS}
alt="Add CSS action"
quality="100"
className="rounded-lg"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
<MdxImage
src={ActionPageurl}
alt="Add inner text action"
quality="100"
className="rounded-lg"
className="max-w-full rounded-lg sm:max-w-3xl"
/>
</div>
</Col>
@@ -135,7 +135,8 @@ Lastly, scroll down to “Recontact Options”. Here you have to choose the corr
<Note>
## Formbricks Widget running? You need to have the Formbricks Widget installed to display the Feedback Box
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart) to install the widget.
in your app. Please follow [this tutorial (Step 4 onwards)](/app-surveys/quickstart)
to install the widget.
</Note>
###

Some files were not shown because too many files have changed in this diff Show More