First-Party Data Strategy
Building a sustainable first-party data foundation for analytics and marketing in a privacy-first world.
Why First-Party Data Matters
The Cookie Deprecation Timeline
| Event | Impact | |-------|--------| | ITP (Safari) | 7-day cookie limit | | ETP (Firefox) | Third-party cookies blocked | | Chrome Privacy Sandbox | Third-party cookies deprecated | | iOS 14.5+ ATT | App tracking requires permission |
Data Quality Comparison
| Data Type | Accuracy | Durability | Privacy Risk | |-----------|----------|------------|--------------| | Third-party | Low | Declining | High | | First-party | High | Stable | Low | | Zero-party | Highest | Stable | Lowest |
Zero-party data: Information customers intentionally share (preferences, survey responses).
First-Party Cookie Strategy
Server-Side Cookie Setting
Using server-side tagging for longer-lived first-party cookies:
// Server-side GTM client sets cookie
// Cookie header in response:
// Set-Cookie: _ga=GA1.2.123456789.1234567890;
// Domain=.example.com;
// Path=/;
// Expires=Thu, 01 Jan 2026 00:00:00 GMT;
// SameSite=Lax;
// Secure
Cookie Comparison
| Cookie Type | Example | Duration (Safari) | Duration (Chrome) | |-------------|---------|-------------------|-------------------| | Client-side JS | gtag() set | 7 days | 2 years | | HTTP Response | Server-side | 2 years | 2 years | | Subdomain | gtm.example.com | 7 days | 2 years | | Same domain | example.com (server) | 2 years | 2 years |
Implementation
- Deploy server-side GTM on first-party subdomain
- Configure GA4 Client to set first-party cookies
- Verify cookie domain matches main site
User Identity Strategy
Identity Resolution Framework
┌─────────────────────────────────────────────────────────┐
│ Identity Graph │
├─────────────────────────────────────────────────────────┤
│ │
│ Anonymous → Known → Authenticated │
│ ─────────────────────────────────────────────────── │
│ • Cookie ID • Email hash • User ID │
│ • Device ID • Phone hash • Account ID │
│ • IP + UA • Form data • CRM ID │
│ │
└─────────────────────────────────────────────────────────┘
Progressive Profiling
Collect information gradually across the customer journey:
| Stage | Data Collected | Method | |-------|----------------|--------| | Awareness | Device, behavior | Automatic (with consent) | | Interest | Preferences, content | Behavioral signals | | Consideration | Email, company | Lead form | | Purchase | Full profile | Transaction | | Retention | Feedback, preferences | Surveys, preferences |
User-Provided Data (UPD)
Collecting and using data users voluntarily provide:
// Capture at form submission
dataLayer.push({
event: 'form_submit',
form_name: 'newsletter_signup',
user_provided_data: {
email: '[email protected]', // Will be hashed
consent_newsletter: true,
consent_marketing: true
}
});
Data Layer as Identity Hub
Unified User Object
// Centralized user data object
window.userData = {
// Anonymous identifiers
anonymous_id: getCookie('_ga')?.split('.').slice(-2).join('.'),
session_id: getSessionId(),
// Known identifiers (when available)
email_hash: null,
phone_hash: null,
// Authenticated identifiers (when logged in)
user_id: null,
customer_id: null,
// Consent state
consent: {
analytics: false,
marketing: false,
personalization: false
}
};
// Push to data layer for GTM
dataLayer.push({
event: 'user_data_ready',
user: window.userData
});
Identity Events
Track identity resolution events:
// User identifies themselves
dataLayer.push({
event: 'user_identified',
method: 'email_capture',
email_hash: hashSHA256(email.toLowerCase().trim())
});
// User authenticates
dataLayer.push({
event: 'user_authenticated',
user_id: '12345',
customer_id: 'cust_abc123',
login_method: 'email_password'
});
Enhanced Conversions
What It Is
Send hashed first-party customer data with conversions for better attribution:
- Email address (hashed)
- Phone number (hashed)
- Name and address (hashed)
Implementation
// Include user data with purchases
dataLayer.push({
event: 'purchase',
transaction_id: 'T12345',
value: 99.99,
currency: 'USD',
// Enhanced conversion data
user_data: {
email: '[email protected]',
phone_number: '+15551234567',
address: {
first_name: 'John',
last_name: 'Doe',
street: '123 Main St',
city: 'San Francisco',
region: 'CA',
postal_code: '94105',
country: 'US'
}
}
});
GTM Configuration
- Enable in Google Ads Conversion tag
- Map variables to user data fields
- GTM handles hashing automatically
Customer Data Platforms (CDP)
Role in First-Party Strategy
A CDP unifies first-party data across touchpoints:
┌─────────────────────────────────────────────────────────┐
│ CDP (Segment, mParticle) │
├─────────────────────────────────────────────────────────┤
│ │
│ Website ──┐ │
│ │ │
│ Mobile ───┼──▶ Unified Profile ──▶ Destinations │
│ │ ▲ • GA4 │
│ CRM ──────┤ │ • Ad Platforms│
│ │ │ • Email │
│ Support ──┘ Identity Resolution • Warehouse │
│ │
└─────────────────────────────────────────────────────────┘
Build vs Buy
| Approach | Pros | Cons | Best For | |----------|------|------|----------| | Build (Data Warehouse) | Full control, lower cost | Requires engineering | Technical teams | | Buy (CDP) | Fast deployment, support | Expensive, vendor lock-in | Enterprise | | Hybrid | Best of both | Complexity | Growth stage |
Data Warehouse as CDP
Modern Data Stack Approach
Website ──▶ Segment ──▶ BigQuery ──▶ Reverse ETL ──▶ Destinations
│
▼
dbt Models
(Identity resolution)
Identity Resolution in SQL
-- Basic identity stitching in BigQuery
WITH identity_graph AS (
SELECT
anonymous_id,
user_id,
email_hash,
FIRST_VALUE(user_id IGNORE NULLS) OVER (
PARTITION BY anonymous_id
ORDER BY timestamp
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
) as resolved_user_id
FROM events
)
SELECT * FROM identity_graph
Privacy-Safe Activation
Hashing Standards
Use SHA-256 for all PII:
async function hashForActivation(value) {
// Normalize: lowercase, trim whitespace
const normalized = value.toLowerCase().trim();
// Hash using Web Crypto API
const encoder = new TextEncoder();
const data = encoder.encode(normalized);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
return hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
}
// Usage
const emailHash = await hashForActivation('[email protected]');
// Returns consistent hash regardless of case/spacing
Consent Requirements
First-party data still requires proper consent:
| Data Use | Consent Required | |----------|------------------| | Analytics | Yes (analytics_storage) | | Personalization | Yes (ad_personalization) | | Advertising | Yes (ad_storage, ad_user_data) | | Internal operations | Legitimate interest (depends) |
Implementation Checklist
Technical Setup
- [ ] Server-side tagging deployed
- [ ] First-party cookies configured
- [ ] Data layer includes user object
- [ ] Hashing implemented correctly
- [ ] Enhanced conversions enabled
Data Collection
- [ ] Progressive profiling forms
- [ ] Account creation flows
- [ ] Preference centers
- [ ] Survey/feedback mechanisms
- [ ] Loyalty programs
Privacy & Governance
- [ ] Consent properly captured
- [ ] Data processing documented
- [ ] Retention policies defined
- [ ] Deletion capabilities ready
- [ ] Vendor agreements signed
Previous: Consent Mode v2 Next: CMP Integration