From a361649e60317092e17758f199babd09d1fa635c Mon Sep 17 00:00:00 2001 From: Usman Baig Date: Sat, 21 Mar 2026 19:52:32 +0100 Subject: [PATCH] feat: add tabbed FAQ, polish installation code blocks, refine integration styling --- app/faq/page.tsx | 108 +++---------------- app/installation/page.tsx | 11 +- app/integrations/page.tsx | 2 +- app/page.tsx | 2 + components/marketing/FAQ.tsx | 169 ++++++++++++++++++++++++++++++ components/marketing/PulseFAQ.tsx | 112 ++++++++++++++++++++ 6 files changed, 307 insertions(+), 97 deletions(-) create mode 100644 components/marketing/FAQ.tsx create mode 100644 components/marketing/PulseFAQ.tsx diff --git a/app/faq/page.tsx b/app/faq/page.tsx index f1bcdca..8917312 100644 --- a/app/faq/page.tsx +++ b/app/faq/page.tsx @@ -1,37 +1,18 @@ 'use client' import { motion } from 'framer-motion' -import { useState } from 'react' -import { ChevronDownIcon } from '@ciphera-net/ui' - -const faqs = [ - { - question: "Is Pulse GDPR compliant?", - answer: "Yes, Pulse is GDPR compliant by design. We don't use cookies, don't collect personal data, and process all data anonymously." - }, - { - question: "Do I need a cookie consent banner?", - answer: "No, you don't need a cookie consent banner. Pulse doesn't use cookies, so it's exempt from cookie consent requirements under GDPR." - }, - { - question: "How does Pulse track visitors?", - answer: "We use a lightweight JavaScript snippet that sends anonymous pageview events. No cookies, no cross-session identifiers (we use sessionStorage only to group events within a single visit), and no cross-site tracking." - }, - { - question: "What data does Pulse collect?", - answer: "We collect anonymous pageview data including page path, referrer, device type, browser, and country (derived from IP at request time; the IP itself is not stored). No personal information is collected." - }, - { - question: "How accurate is the data?", - answer: "Our data is highly accurate. We exclude bot traffic and data center visits. Since we don't use cookies, we count unique sessions rather than unique users." - }, - { - question: "Can I export my data?", - answer: "Yes, you can access all your analytics data through the dashboard. We're working on export functionality for bulk data downloads." - } -] +import PulseFAQ from '@/components/marketing/PulseFAQ' // * JSON-LD FAQ Schema for rich snippets +const faqs = [ + { question: "Is Pulse GDPR compliant?", answer: "Yes, Pulse is GDPR compliant by design. We don't use cookies, don't collect personal data, and process all data anonymously." }, + { question: "Do I need a cookie consent banner?", answer: "No, you don't need a cookie consent banner. Pulse doesn't use cookies, so it's exempt from cookie consent requirements under GDPR." }, + { question: "How does Pulse track visitors?", answer: "We use a lightweight JavaScript snippet that sends anonymous pageview events. No cookies, no cross-session identifiers (we use sessionStorage only to group events within a single visit), and no cross-site tracking." }, + { question: "What data does Pulse collect?", answer: "We collect anonymous pageview data including page path, referrer, device type, browser, and country (derived from IP at request time; the IP itself is not stored). No personal information is collected." }, + { question: "How accurate is the data?", answer: "Our data is highly accurate. We exclude bot traffic and data center visits. Since we don't use cookies, we count unique sessions rather than unique users." }, + { question: "Can I export my data?", answer: "Yes, you can access all your analytics data through the dashboard. We're working on export functionality for bulk data downloads." }, +] + const faqSchema = { '@context': 'https://schema.org', '@type': 'FAQPage', @@ -45,47 +26,6 @@ const faqSchema = { })), } -function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) { - const [isOpen, setIsOpen] = useState(false) - - return ( - - - {isOpen && ( - -

- {faq.answer} -

-
- )} -
- ) -} - export default function FAQPage() { return ( <> @@ -94,29 +34,9 @@ export default function FAQPage() { type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(faqSchema) }} /> - -
- - FAQ -

- Frequently asked questions -

-

- Learn more about how Pulse respects your privacy and handles your data. -

-
-
- {faqs.map((faq, index) => ( - - ))} -
+
+ {/* * CTA */} -

+

Still have questions?

Contact us diff --git a/app/installation/page.tsx b/app/installation/page.tsx index effd9a3..a086b61 100644 --- a/app/installation/page.tsx +++ b/app/installation/page.tsx @@ -31,7 +31,7 @@ export default function InstallationPage() {

Add the snippet

Just add this snippet to your <head> tag in your layout or index file.

-
+
@@ -53,6 +53,13 @@ export default function InstallationPage() { ></script>
+
+ 1.6 KB gzipped + + + Non-blocking, async + +
@@ -61,7 +68,7 @@ export default function InstallationPage() {

Track custom events (e.g. signup, purchase) with pulse.track('event_name'). Use letters, numbers, and underscores only. Define goals in your site Settings → Goals & Events to see counts in the dashboard.

-
+
diff --git a/app/integrations/page.tsx b/app/integrations/page.tsx index 4be357a..8582f22 100644 --- a/app/integrations/page.tsx +++ b/app/integrations/page.tsx @@ -143,7 +143,7 @@ export default function IntegrationsPage() { value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Search integrations..." - className="w-full pl-12 pr-16 py-3 bg-neutral-900/70 backdrop-blur-sm border border-neutral-800 rounded-xl text-white placeholder:text-neutral-400 focus:outline-none focus:ring-2 focus:ring-brand-orange/50 focus:border-brand-orange/50 transition-all" + className="w-full pl-12 pr-16 py-3 bg-neutral-900/70 backdrop-blur-sm border border-white/[0.08] rounded-xl text-white placeholder:text-neutral-400 focus:outline-none focus:ring-2 focus:ring-brand-orange/50 focus:border-brand-orange/50 transition-all" /> {query ? ( + ))} +
+); + +const FAQList = ({ faqData, selected }: { faqData: Record; selected: string }) => ( +
+ + {Object.entries(faqData).map(([category, questions]) => { + if (selected === category) { + return ( + + {questions.map((faq, index) => ( + + ))} + + ); + } + return null; + })} + +
+); + +const FAQItemComponent = ({ question, answer }: FAQItem) => { + const [isOpen, setIsOpen] = useState(false); + + return ( + + + +

{answer}

+
+
+ ); +}; diff --git a/components/marketing/PulseFAQ.tsx b/components/marketing/PulseFAQ.tsx new file mode 100644 index 0000000..1433178 --- /dev/null +++ b/components/marketing/PulseFAQ.tsx @@ -0,0 +1,112 @@ +'use client' + +import { FAQ } from '@/components/marketing/FAQ' + +const categories: Record = { + general: "General", + setup: "Setup", + privacy: "Privacy & Compliance", + technical: "Technical", +} + +const faqData: Record = { + general: [ + { + question: "What is Pulse?", + answer: "Pulse is a privacy-first website analytics platform by Ciphera. It tracks pageviews, unique visitors, referrers, and geographic data without using cookies, fingerprinting, or collecting any personal data. It's a privacy-respecting alternative to Google Analytics.", + }, + { + question: "Is Pulse free?", + answer: "Yes, Pulse is free for personal websites. We plan to offer a paid Pro tier for teams and high-traffic sites in the future, but the free tier will always be available.", + }, + { + question: "Can I migrate from Google Analytics?", + answer: "Pulse is not a drop-in replacement for Google Analytics — it's fundamentally different by design. It doesn't track individual users or sessions, so historical GA data can't be imported. However, you can run both side by side during a transition period.", + }, + { + question: "Is Pulse open source?", + answer: "The Pulse client — dashboard and tracking script — are open source and available on GitHub. You can inspect every line of code that runs on your site and verify our privacy claims.", + }, + { + question: "How is Pulse different from Plausible or Fathom?", + answer: "Pulse shares the privacy-first philosophy with Plausible and Fathom, but it's built on Swiss infrastructure with Swiss data protection laws. The client — dashboard and tracking script — are open source, and Pulse is part of the Ciphera ecosystem, giving you a unified privacy-first stack.", + }, + ], + setup: [ + { + question: "How do I install Pulse?", + answer: "Add a single script tag to your site's section. That's it. No npm packages, no build steps, no configuration files. The script is under 2KB gzipped and loads asynchronously.", + }, + { + question: "Does Pulse work with my framework?", + answer: "Yes. Pulse works with any website or framework: plain HTML, React, Next.js, Vue, Nuxt, Svelte, WordPress, Shopify, and more. If it renders HTML, Pulse works with it.", + }, + { + question: "How do I verify Pulse is working?", + answer: "After adding the script tag, visit your site and check the Pulse dashboard. You should see your visit appear in real-time within seconds. The dashboard shows a live visitor count and updates every few seconds.", + }, + { + question: "Can I track multiple websites?", + answer: "Yes. Each website gets its own dashboard. You can add as many sites as you need from the Pulse dashboard by adding the script tag with a different data-domain attribute.", + }, + { + question: "Does Pulse slow down my website?", + answer: "No. The Pulse script is under 2KB gzipped — about 20x smaller than Google Analytics. It loads asynchronously with the defer attribute, meaning it never blocks page rendering or affects your Core Web Vitals scores.", + }, + ], + privacy: [ + { + question: "Do I need a cookie consent banner for Pulse?", + answer: "No. Because Pulse doesn't use cookies, fingerprinting, or any form of persistent identifier, it's exempt from ePrivacy cookie consent requirements. You can use Pulse without any consent banner.", + }, + { + question: "Is Pulse GDPR compliant?", + answer: "Yes, by architecture — not by configuration. Pulse doesn't collect any personal data as defined by GDPR Article 4. There are no data subjects in the dataset, so DSAR requests don't apply. No DPA is required.", + }, + { + question: "What happens to IP addresses?", + answer: "IP addresses are used only at the network edge for country-level geolocation. They are immediately discarded after the geo lookup — never stored, never logged, never written to disk. We can't retrieve them even if asked.", + }, + { + question: "Where is my analytics data stored?", + answer: "All data is processed and stored on Swiss infrastructure, protected by the Swiss Federal Act on Data Protection (FADP). Data never leaves Swiss jurisdiction.", + }, + { + question: "Can Pulse identify individual users?", + answer: "No. Pulse is architecturally incapable of identifying individual users. Each pageview is treated as an independent, anonymous event. There are no user IDs, session IDs, or any form of persistent tracking.", + }, + ], + technical: [ + { + question: "How does Pulse count unique visitors without cookies?", + answer: "Pulse uses a privacy-safe hashing method that generates a daily rotating identifier from non-personal data points. This allows approximate unique visitor counts without tracking individuals across sessions or days.", + }, + { + question: "Does Pulse have an API?", + answer: "Yes. Pulse provides a REST API for programmatic access to your analytics data. You can use it to build custom dashboards, integrate with other tools, or export your data.", + }, + { + question: "What metrics does Pulse track?", + answer: "Pulse tracks pageviews, unique visitors, bounce rate, visit duration, referrer sources, UTM parameters, device type, browser, operating system, and country-level geolocation.", + }, + { + question: "Can I export my data?", + answer: "Yes. The dashboard includes an export feature that lets you download your analytics data. You can also use the API for automated exports.", + }, + { + question: "Does Pulse support custom events?", + answer: "Custom event tracking is on our roadmap. Currently, Pulse focuses on pageview analytics. We plan to add lightweight custom event support that maintains our zero-personal-data architecture.", + }, + ], +} + +export default function PulseFAQ() { + return ( + + ) +}