技能 编程开发 Webflow数据安全与合规处理

Webflow数据安全与合规处理

v20260423
webflow-data-handling
本技能指导用户如何处理Webflow生态系统中的敏感数据,包括从表单提交和电商订单中识别、加密和脱敏个人身份信息(PII)。核心目标是确保数据处理流程符合GDPR、CCPA等国际数据隐私法规,并建立完善的数据留存机制,实现数据合规化。
获取技能
312 次下载
概览

Webflow Data Handling

Overview

Handle sensitive data correctly when working with the Webflow Data API v2. Covers PII in form submissions, ecommerce customer data, CMS content classification, GDPR/CCPA compliance patterns, and data retention policies.

Prerequisites

  • Understanding of GDPR/CCPA requirements
  • Webflow API token with forms:read, ecommerce:read scopes
  • Database for audit logging
  • Scheduled job infrastructure for data cleanup

Webflow Data Classification

Source Data Type PII Risk Handling
Form submissions Email, name, phone, message High Encrypt at rest, redact in logs
Ecommerce orders Name, email, address, payment High Never log, minimal retention
CMS items Blog posts, team bios, products Low-Medium May contain names/photos
Site analytics Page views, sessions Low Aggregate when possible
API tokens Access credentials Critical Never log, rotate quarterly

Instructions

Step 1: PII Detection in Form Submissions

const PII_PATTERNS = [
  { type: "email", regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g },
  { type: "phone", regex: /\b\d{3}[-.]?\d{3}[-.]?\d{4}\b/g },
  { type: "ssn", regex: /\b\d{3}-\d{2}-\d{4}\b/g },
  { type: "credit_card", regex: /\b\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}\b/g },
];

function detectPII(text: string): Array<{ type: string; found: boolean }> {
  return PII_PATTERNS.map(p => ({
    type: p.type,
    found: p.regex.test(text),
  })).filter(r => r.found);
}

// Scan form submissions for PII before logging
async function processFormSubmission(formId: string) {
  const { formSubmissions } = await webflow.forms.listSubmissions(formId);

  for (const sub of formSubmissions || []) {
    const rawData = JSON.stringify(sub.formData);
    const piiFindings = detectPII(rawData);

    if (piiFindings.length > 0) {
      console.warn(`PII detected in submission ${sub.id}: ${piiFindings.map(f => f.type).join(", ")}`);
      // Log redacted version only
      console.log("Form data:", redactPII(sub.formData || {}));
    }
  }
}

Step 2: PII Redaction

function redactPII(data: Record<string, any>): Record<string, any> {
  const sensitiveFields = new Set([
    "email", "phone", "telephone", "mobile", "ssn",
    "password", "credit-card", "card-number", "address",
    "full-name", "first-name", "last-name",
  ]);

  const redacted: Record<string, any> = {};

  for (const [key, value] of Object.entries(data)) {
    const normalizedKey = key.toLowerCase().replace(/[\s_]/g, "-");

    if (sensitiveFields.has(normalizedKey)) {
      redacted[key] = "[REDACTED]";
    } else if (typeof value === "string") {
      // Redact inline PII patterns
      let cleaned = value;
      for (const pattern of PII_PATTERNS) {
        cleaned = cleaned.replace(pattern.regex, `[${pattern.type.toUpperCase()}_REDACTED]`);
      }
      redacted[key] = cleaned;
    } else {
      redacted[key] = value;
    }
  }

  return redacted;
}

// Usage in logging
async function logFormData(formData: Record<string, any>) {
  console.log("Form submission (redacted):", redactPII(formData));
}

Step 3: Ecommerce Data Handling

// Order data contains high-sensitivity PII
async function processOrder(siteId: string, orderId: string) {
  const order = await webflow.orders.get(siteId, orderId);

  // NEVER log full customer info
  const safeOrderLog = {
    orderId: order.orderId,
    status: order.status,
    itemCount: order.purchasedItems?.length,
    totalCents: order.customerPaid?.value,
    // Redact customer info
    customer: {
      hasEmail: !!order.customerInfo?.email,
      hasAddress: !!order.shippingAddress,
      // Never: order.customerInfo?.email
      // Never: order.shippingAddress?.addressLine1
    },
    createdAt: order.acceptedOn,
  };

  console.log("Order processed:", safeOrderLog);
}

Step 4: GDPR — Data Subject Access Request (DSAR)

interface DataExport {
  source: string;
  exportedAt: string;
  requestedBy: string;
  data: {
    formSubmissions: Array<{ formName: string; submittedAt: string; data: Record<string, any> }>;
    orders: Array<{ orderId: string; status: string; total: number; items: string[] }>;
  };
}

async function exportUserData(siteId: string, userEmail: string): Promise<DataExport> {
  const exportData: DataExport = {
    source: "Webflow",
    exportedAt: new Date().toISOString(),
    requestedBy: userEmail,
    data: { formSubmissions: [], orders: [] },
  };

  // 1. Find form submissions by email
  const { forms } = await webflow.forms.list(siteId);
  for (const form of forms || []) {
    const { formSubmissions } = await webflow.forms.listSubmissions(form.id!);
    for (const sub of formSubmissions || []) {
      const formData = sub.formData || {};
      // Check all fields for matching email
      const hasEmail = Object.values(formData).some(
        v => typeof v === "string" && v.toLowerCase() === userEmail.toLowerCase()
      );
      if (hasEmail) {
        exportData.data.formSubmissions.push({
          formName: form.displayName!,
          submittedAt: sub.submittedAt!,
          data: formData,
        });
      }
    }
  }

  // 2. Find orders by email
  const { orders } = await webflow.orders.list(siteId);
  for (const order of orders || []) {
    if (order.customerInfo?.email?.toLowerCase() === userEmail.toLowerCase()) {
      exportData.data.orders.push({
        orderId: order.orderId!,
        status: order.status!,
        total: (order.customerPaid?.value || 0) / 100,
        items: order.purchasedItems?.map(i => i.productName || "Unknown") || [],
      });
    }
  }

  return exportData;
}

Step 5: GDPR — Right to Deletion

async function deleteUserData(
  siteId: string,
  userEmail: string
): Promise<{ deleted: string[]; retained: string[] }> {
  const result = { deleted: [] as string[], retained: [] as string[] };

  // Note: Webflow API does not currently support deleting form submissions
  // via API. You must delete them through the Webflow dashboard.
  // However, you can delete your local copies:

  // 1. Delete local form submission copies
  await db.formSubmissions.deleteMany({ email: userEmail, source: "webflow" });
  result.deleted.push("Local form submission copies");

  // 2. Delete local order copies (keep anonymized for accounting)
  await db.orders.updateMany(
    { email: userEmail, source: "webflow" },
    { $set: { email: "[DELETED]", name: "[DELETED]", address: "[DELETED]" } }
  );
  result.retained.push("Anonymized order records (legal requirement)");

  // 3. Audit log (required — never delete audit logs)
  await db.auditLog.insertOne({
    action: "GDPR_DELETION",
    email: userEmail,
    service: "webflow",
    timestamp: new Date(),
    deletedSources: result.deleted,
    retainedSources: result.retained,
  });
  result.retained.push("Audit log entry");

  return result;
}

Step 6: Data Retention Policy

Data Type Retention Reason Auto-Cleanup
Form submissions 90 days Business need Yes
Order records 7 years Tax/accounting No
API call logs 30 days Debugging Yes
Error logs 90 days Root cause analysis Yes
Audit logs 7 years Compliance No
Cached CMS content 24 hours Performance Yes (TTL)
async function cleanupExpiredData() {
  const now = new Date();

  // Delete form submissions older than 90 days
  const formCutoff = new Date(now);
  formCutoff.setDate(formCutoff.getDate() - 90);
  await db.formSubmissions.deleteMany({
    source: "webflow",
    createdAt: { $lt: formCutoff },
    type: { $nin: ["audit", "compliance"] },
  });

  // Delete API logs older than 30 days
  const logCutoff = new Date(now);
  logCutoff.setDate(logCutoff.getDate() - 30);
  await db.apiLogs.deleteMany({
    service: "webflow",
    createdAt: { $lt: logCutoff },
  });

  console.log("Data cleanup completed");
}

// Schedule daily at 3 AM
// cron: "0 3 * * *"

Output

  • PII detection for form submissions and order data
  • Redaction layer for logging sensitive Webflow data
  • GDPR DSAR export (forms + orders by email)
  • Right to deletion with audit trail
  • Data retention policy with automated cleanup

Error Handling

Issue Cause Solution
PII in logs Missing redaction wrapper Wrap all logging with redactPII()
DSAR incomplete Not scanning all forms Iterate all forms in site
Deletion failed No API for form deletion Delete via Webflow dashboard
Audit gap Missing log entries Ensure audit logging in all deletion paths

Resources

Next Steps

For enterprise access control, see webflow-enterprise-rbac.

信息
Category 编程开发
Name webflow-data-handling
版本 v20260423
大小 9.48KB
更新时间 2026-04-28
语言