Every other analytics SDK competes on "flexibility"—more custom properties, more event types, more data. We went the other direction. We architecturally block custom properties to prevent accidental PII leaks. Most developers think we're crazy. We think we're saving them from a lawsuit.
Every major analytics platform—Mixpanel, Amplitude, Firebase, PostHog—has a feature they're proud of: custom event properties. Track any event. Attach any data. Infinite flexibility.
We removed that feature entirely. Our SDK doesn't have a properties parameter. Our API rejects any data beyond 5 predefined fields. And we think this makes us better, not worse.
This isn't a limitation—it's a safety feature. Here's why.
🪤 The "Infinite Attributes" Trap
Custom properties feel like a superpower when you're building. Need to segment users? Add a property. Want to track purchase amounts? Add a property. Debugging an edge case? Log the user's input as a property.
The problem isn't today. The problem is 18 months from now when:
-
✗
A junior developer adds
track("feedback", {message: userInput})—anduserInputcontains email addresses, phone numbers, or worse -
✗
Someone debugging a payment flow adds
track("payment_error", {debug: paymentResponse})—andpaymentResponsecontains credit card tokens -
✗
A health app tracks
track("symptom_selected", {symptom: userSymptom})—congratulations, you're now storing protected health information in your analytics database -
✗
An A/B test logs
track("variant_shown", {userId: user.id})—and now your "anonymous" analytics can be linked to individual users
Every custom property is a door you're leaving unlocked. Most of the time, nothing walks through. But when it does, you have a data spill—and potentially a regulatory incident.
💀 A Real Horror Story
Here's a scenario that's happened at companies you've heard of:
The Timeline of a Data Spill
track("purchase", {note: orderNote}) to help debug a checkout issue. Ships to production.
orderNote sometimes contains delivery instructions like "Ring bell for John Smith at 555-1234" or "Leave at back door, gate code 9876".
The flexibility of custom properties enabled this. The developer wasn't malicious—they were debugging. But the architecture allowed a debug statement to become a 14-month data collection program.
🏗️ The Architecture of Constraint
Our approach is different. We enforce data minimization at the API level—not as a policy, but as an architectural constraint.
The Strict 5-Field Model
Every event we store has exactly 5 fields. No more, no less:
- event_name — What happened ("upgrade_button_clicked")
- session_id — Anonymous session identifier (RAM-only, rotates every 2 hours)
- timestamp — When it happened
- platform — iOS or Android
- country — Derived from IP (IP is immediately discarded)
That's it. The API rejects any additional data. The SDK doesn't have a properties parameter. You can't accidentally leak PII because there's nowhere to put it.
What This Looks Like in Code
Traditional Analytics SDK (The Risk)
// Nothing stops you from doing this:
Analytics.track("signup", properties: [
"email": user.email, // ✅ Sent (and now stored forever)
"name": user.fullName, // ✅ Sent (PII in your analytics)
"debug": user.toString() // ✅ Sent (who knows what's in there)
])
Respectlytics SDK (The Guardrail)
// No properties parameter exists:
Respectlytics.track("signup_completed") // ✅ That's it. Nothing else to add.
// This doesn't compile:
Respectlytics.track("signup", properties: [...]) // ❌ Error: extra argument 'properties'
// Even if you hit the API directly with extra fields:
// POST /api/v1/track
// {"event_name": "signup", "email": "[email protected]"}
// → API accepts request but silently discards "email"
🛡️ Defensible by Default
We call our philosophy Return of Avoidance (ROA)—the best way to handle sensitive data is to never collect it. But the real payoff isn't philosophical. It's practical.
The Audit Question You Never Want to Hear
Imagine an auditor—internal, external, or regulatory—asks:
"Can you confirm that no personal data has been collected in your analytics events over the past 3 years?"
With traditional analytics, answering this requires:
-
⚠
Auditing every
track()call in your codebase - ⚠ Reviewing 3 years of git history for property changes
- ⚠ Scanning your analytics database for patterns that look like emails, phone numbers, or addresses
- ⚠ Hoping no contractor or intern added a debug statement you missed
With architectural constraints, the answer is simpler:
"Yes. It's technically impossible."
Our API only accepts 5 predefined fields. Custom properties are rejected at the API level. Here's the documentation. Here's the API response for rejected fields. There's no code review required—the architecture enforces the policy.
This is what defensible by design means. Not a policy that developers might follow. An architecture that makes violations impossible.
📊 How to Measure Intent Without Identity
The first objection we hear: "But how do I segment users without custom properties?"
The answer: use descriptive event names instead of generic events with properties.
Event Naming Taxonomy (The Pattern)
| ❌ Traditional (Risky) | ✅ Respectlytics (Safe) |
|---|---|
track("click", {button: "upgrade"}) |
track("upgrade_button_clicked") |
track("purchase", {plan: "pro"}) |
track("pro_plan_purchased") |
track("feature_used", {user_type: "premium"}) |
track("premium_user_feature_x_used") |
track("error", {code: 500, page: "/checkout"}) |
track("checkout_error_500") |
track("search", {query: userQuery}) |
track("search_performed") |
Notice the last row. You lose the search query—intentionally. Because userQuery might be "pharmacy near 123 Main Street" or "Dr. Smith appointment." That's the kind of data that becomes a liability.
You still know searches are happening. You know how many. You know which platform. You know the trend over time. You just don't know what people searched for—and you probably didn't need to.
⚔️ The Counter-Arguments (And Our Responses)
"But I need custom properties for debugging!"
Use a logging system for debugging—not analytics. Logs can have short retention, access controls, and PII scrubbing. Analytics is a long-term data warehouse. It's the wrong place for debug data.
"What if I'm careful about what I track?"
You might be. But can you guarantee every developer on your team, for the next 5 years, will be equally careful? Policies fail. Architecture doesn't.
"This limits what I can analyze!"
Yes. That's the point. We help you analyze behavior (what features are used, where users drop off, conversion rates) without analyzing individuals. If you need user-level analytics, you need a different tool—and a more complex privacy posture.
"Our privacy team reviews all tracking changes."
Great! How many PRs did they review last month? How confident are you that the intern's hotfix at 2 AM was caught? Architectural constraints work 24/7, never get tired, and never miss a code path.
❓ Frequently Asked Questions
Q: Can I track purchase amounts or revenue?
Not as properties. But you can use event naming: purchase_tier_1, purchase_tier_2, purchase_tier_3. You get tier distribution without exact amounts. If you need exact revenue tracking, that belongs in your billing system, not your analytics.
Q: How do I track A/B test variants?
Embed the variant in the event name: checkout_v2_completed vs checkout_v1_completed. You can compare conversion rates between variants without storing which user saw which variant.
Q: What about user segmentation (free vs paid users)?
Use event prefixes: free_user_feature_x vs paid_user_feature_x. Your client knows if the user is free or paid—encode that knowledge in the event name, not a property that could also carry other data.
Q: Doesn't this create event name explosion?
It creates intentional event names. Traditional analytics creates event name simplicity with property explosion. We're just being explicit about what you're tracking instead of hiding it in unstructured properties.
💡 Key Takeaways
- → Custom properties are an uncontrolled surface for PII leaks—every property is a door you're leaving unlocked
- → Architectural constraints beat policies—code review fails; API rejection doesn't
- → Defensible by default—answer "Do you collect PII?" with documentation, not database scans
- → Event naming taxonomy replaces properties—you lose flexibility, gain safety
Legal Disclaimer
This article provides architectural recommendations for privacy-conscious analytics design. It does not constitute legal advice. Privacy requirements vary by jurisdiction and change over time. Consult your legal team to determine the requirements that apply to your situation.
Additional Resources
- Respectlytics SDK Documentation - See our 5-field model in action (Swift, Kotlin, Flutter, React Native)
- Mobile Analytics Without Personal Data - Technical deep dive on session-based architecture
- Mobile App Analytics Best Practices - Complete guide to Return of Avoidance (ROA)
- Mobile App Metrics Builder Tool - Generate your event taxonomy without properties