https://github.com/91369673/reddit-pixel-shopify-server-side-tracking
Server-side conversion tracking for Reddit Ads using Shopify webhooks and Reddit Conversions API
https://github.com/91369673/reddit-pixel-shopify-server-side-tracking
conversions-api docker ecommerce nodejs reddit reddit-ads reddit-pixel server-side-tracking shopify webhooks
Last synced: about 2 months ago
JSON representation
Server-side conversion tracking for Reddit Ads using Shopify webhooks and Reddit Conversions API
- Host: GitHub
- URL: https://github.com/91369673/reddit-pixel-shopify-server-side-tracking
- Owner: 91369673
- License: mit
- Created: 2025-11-22T03:13:56.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-11-22T03:29:33.000Z (6 months ago)
- Last Synced: 2025-11-22T05:30:14.380Z (6 months ago)
- Topics: conversions-api, docker, ecommerce, nodejs, reddit, reddit-ads, reddit-pixel, server-side-tracking, shopify, webhooks
- Language: JavaScript
- Size: 16.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Reddit Pixel Shopify Server-Side Tracking
Server-side conversion tracking for Reddit Ads using Shopify webhooks and Reddit Conversions API. This implementation bypasses browser-based tracking limitations (ad blockers, privacy settings, iOS restrictions) to capture conversions that client-side pixels miss.
## Why Server-Side Tracking?
Reddit officially recommends using both Pixel and Conversions API together for optimal tracking accuracy. According to their documentation:
> "CAPI is more resilient to signal loss because it operates server-side, making it less susceptible to ad blockers and browser restrictions."
Client-side pixel tracking loses 30-50% of conversions due to:
- Ad blockers
- Browser privacy settings (Safari, Firefox)
- iOS App Tracking Transparency
- Third-party cookie blocking
This server-side implementation captures conversions that browser-based tracking misses by sending data directly from your server to Reddit's API.
## Features
- ✅ Production-ready Docker setup
- ✅ HMAC webhook verification (Shopify security)
- ✅ PII hashing (SHA-256 for privacy)
- ✅ Event deduplication (PostgreSQL)
- ✅ Automatic retry logic with exponential backoff
- ✅ Rate limiting handling (429 responses)
- ✅ Comprehensive logging (Winston)
- ✅ Health check endpoint
- ✅ SSL/HTTPS support (Nginx reverse proxy example)
## Quick Start
**Prerequisites:**
- Linux server with Docker installed
- Domain/subdomain pointing to your server
- Reddit Ads account with Pixel created
- Shopify store with admin access
**Installation (5 minutes):**
```bash
# Clone repository
git clone https://github.com/91369673/reddit-pixel-shopify-server-side-tracking.git
cd reddit-pixel-shopify-server-side-tracking
# Copy environment template
cp .env.example .env
# Edit .env with your credentials
nano .env
# Start services
docker compose up -d
# Check logs
docker compose logs -f reddit-capi
```
## Configuration
### 1. Reddit Ads Manager
1. Go to Reddit Ads Manager → Events Manager
2. Create new Pixel
3. Copy **Pixel ID** (format: `t2_abc123`)
4. Go to Settings → Conversions API
5. Generate **Access Token**
6. Add to `.env`:
```env
REDDIT_PIXEL_ID=t2_your_pixel_id
REDDIT_ACCESS_TOKEN=your_access_token_here
```
### 2. Shopify Webhooks
1. Shopify Admin → Settings → Notifications → Webhooks
2. Create webhook:
- **Event:** Order creation
- **Format:** JSON
- **URL:** `https://your-domain.com/webhooks/shopify`
- **API version:** Latest
3. Copy **Signing Secret** → add to `.env`:
```env
SHOPIFY_WEBHOOK_SECRET=your_webhook_secret
```
4. Restart: `docker compose restart reddit-capi`
### 3. Nginx Reverse Proxy (Optional but Recommended)
Create `/etc/nginx/sites-available/reddit-tracking.conf`:
```nginx
server {
listen 443 ssl http2;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
}
```
Enable and reload:
```bash
ln -s /etc/nginx/sites-available/reddit-tracking.conf /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
```
## Architecture
```
Shopify Store (order created)
|
v
Shopify Webhook (HTTPS POST)
|
v
Nginx Reverse Proxy (SSL termination)
|
v
Node.js Application (Docker container)
|
v
1. HMAC Verification
2. Event Transformation
3. PII Hashing (SHA-256)
4. Deduplication Check
5. Send to Reddit CAPI
6. Log Result
|
v
Reddit Ads Platform
```
## Environment Variables
| Variable | Required | Description | Example |
|----------|----------|-------------|---------|
| `SHOPIFY_WEBHOOK_SECRET` | Yes | Shopify webhook signing secret | `ba32d1d12da1ffc...` |
| `REDDIT_PIXEL_ID` | Yes | Reddit Pixel ID from Events Manager | `t2_abc123` |
| `REDDIT_ACCESS_TOKEN` | Yes | Reddit Conversions API access token | `eyJhbGciOiJSUzI1...` |
| `DB_PASSWORD` | Yes | PostgreSQL database password | `strong_password` |
| `PORT` | No | Application port (default: 3000) | `3000` |
## Testing
**Health check:**
```bash
curl https://your-domain.com/health
```
**Expected response:**
```json
{
"status": "healthy",
"timestamp": "2025-11-22T12:00:00.000Z",
"uptime": 12345.67,
"database": "connected"
}
```
**Send test webhook from Shopify:**
1. Shopify Admin → Settings → Notifications → Webhooks
2. Click on your webhook
3. "Send test notification"
4. Check logs: `docker compose logs -f reddit-capi`
**Verify in Reddit:**
1. Reddit Ads Manager → Events Manager
2. Click your Pixel → "Test Events" tab
3. Event should appear within a few minutes
## Monitoring
**View logs:**
```bash
docker compose logs -f reddit-capi
```
**Check recent events:**
```bash
docker compose exec postgres psql -U reddit_capi -d reddit_capi -c \
"SELECT event_id, event_type, status, created_at FROM events ORDER BY created_at DESC LIMIT 10;"
```
**Failed events:**
```bash
docker compose exec postgres psql -U reddit_capi -d reddit_capi -c \
"SELECT event_id, error_message FROM events WHERE status = 'failed';"
```
## Troubleshooting
### Events Not Appearing in Reddit
**Check logs for API errors:**
```bash
docker compose logs reddit-capi | grep "Reddit API error"
```
**Common errors:**
| Error | Cause | Solution |
|-------|-------|----------|
| "unexpected type number" | Value sent as decimal | Verify multiplication by 100 in transformer |
| "unknown field event_id" | Invalid field in payload | Remove `event_id` from Reddit event object |
| 401 Unauthorized | Invalid access token | Regenerate token in Reddit Events Manager |
| 429 Too Many Requests | Rate limiting | Handled automatically with retry logic |
### HMAC Verification Failed
```bash
# Check if secret matches
docker compose exec reddit-capi printenv SHOPIFY_WEBHOOK_SECRET
# Update .env and restart
docker compose restart reddit-capi
```
### Database Connection Issues
```bash
# Check PostgreSQL status
docker compose ps postgres
# Test connection
docker compose exec postgres pg_isready -U reddit_capi
```
## Database Schema
```sql
CREATE TABLE events (
event_id VARCHAR(255) PRIMARY KEY,
event_type VARCHAR(50) NOT NULL,
shopify_id VARCHAR(255) NOT NULL,
shopify_payload JSONB,
reddit_payload JSONB,
reddit_response JSONB,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
sent_at TIMESTAMP,
status VARCHAR(20) DEFAULT 'pending',
error_message TEXT
);
```
## Security Features
1. **HMAC Verification:** Every webhook validated with SHA-256 HMAC
2. **HTTPS Only:** TLS 1.2/1.3 encryption
3. **Localhost Binding:** Container only accessible via reverse proxy
4. **PII Hashing:** Email/phone SHA-256 hashed before sending to Reddit
5. **Environment Secrets:** All sensitive data in `.env` (git-ignored)
## Advanced Configuration
### Multi-Currency Support
The implementation automatically handles different currencies. For currencies with non-standard decimal places:
```javascript
// Zero-decimal currencies (JPY, KRW): multiply by 1
// Standard currencies (USD, EUR): multiply by 100
// Three-decimal currencies (BHD, KWD): multiply by 1000
value: Math.round(parseFloat(order.total_price) * 100)
```
### Additional Event Types
Extend `src/services/shopifyTransformer.js` for more events:
```javascript
export function transformProductView(product) {
return {
event_at: new Date().toISOString(),
event_type: { tracking_type: 'ViewContent' },
// ... user data
event_metadata: {
conversion_id: `product_${product.id}_${Date.now()}`,
item_id: String(product.id),
},
};
}
```
## License
MIT License - see [LICENSE](LICENSE) file for details.
## Contributing
Contributions welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Test your changes
4. Submit a pull request
## Support
- **Issues:** [GitHub Issues](https://github.com/91369673/reddit-pixel-shopify-server-side-tracking/issues)
- **Documentation:** [Full setup guide](https://www.tva.sg/reddit-pixel-tracking-for-shopify-server-side-implementation-with-conversions-api/)
- **Reddit API Docs:** [Reddit Conversions API](https://reddithelp.com/hc/en-us/articles/4410892225940-Reddit-Conversions-API)
## Acknowledgments
Based on production implementation for live Shopify stores. Tested with:
- Reddit Conversions API v2.0
- Shopify API 2025-01
- Docker Compose v2.x
- PostgreSQL 16
- Node.js 18
---
**⭐ If this helped you, consider starring the repo!**