reddit_pixel 1.0.0 copy "reddit_pixel: ^1.0.0" to clipboard
reddit_pixel: ^1.0.0 copied to clipboard

A privacy-centric, backend-agnostic Flutter library for Reddit Conversions API (CAPI) v3. Supports direct and proxy transport modes with offline-first persistence.

reddit_pixel #

Pub Version Build Status Style: Very Good Analysis Codecov License: BSD-3

A privacy-centric, backend-agnostic Flutter library for Reddit Conversions API (CAPI) v3. Track conversion events with offline-first persistence, automatic retry, and PII hashing.

Features #

  • Privacy-First: No tracking dependencies by default. IDFA/AAID support requires explicit opt-in
  • Backend-Agnostic: Use proxy mode (recommended) or direct mode for development
  • Offline-First: Events are queued locally with Hive and sent when online
  • Performance: PII normalization and SHA-256 hashing run in isolates
  • Automatic Retry: Exponential backoff for failed requests
  • All Event Types: Purchase, SignUp, Lead, AddToCart, AddToWishlist, Search, ViewContent, PageVisit, and Custom events

See the example for runnable examples of various usages.

Platform Support #

Android iOS macOS Web Linux Windows

Features Supported #

Feature Android iOS macOS Web Linux Windows
Proxy Transport
Direct Transport
Offline Queue
IDFA/AAID Support

Installation #

Add the dependency to your pubspec.yaml:

dependencies:
  reddit_pixel: ^0.0.1

Then run:

flutter pub get

Configuration #

For production, use a proxy server to keep your Reddit API token secure. Your server should:

  1. Receive the event payload from this library
  2. Add the Reddit API authorization header
  3. Forward the request to Reddit's Conversions API
  4. Return the response

Example proxy endpoint (Node.js/Express):

app.post('/api/reddit-events/:pixelId', async (req, res) => {
  const response = await fetch(
    `https://ads-api.reddit.com/api/v3/pixels/${req.params.pixelId}/conversion_events`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${process.env.REDDIT_API_TOKEN}`,
      },
      body: JSON.stringify(req.body),
    }
  );
  res.status(response.status).json(await response.json());
});

iOS Configuration #

If you plan to use IDFA tracking, add to your Info.plist:

<key>NSUserTrackingUsageDescription</key>
<string>This identifier will be used to measure advertising effectiveness.</string>

Android Configuration #

No special configuration required. For AAID tracking, Google Play Services must be available on the device.

Usage #

Basic Usage #

import 'package:reddit_pixel/reddit_pixel.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  // Initialize with proxy mode (recommended)
  await RedditPixel.initialize(
    pixelId: 'your-pixel-id',
    proxyUrl: 'https://your-server.com/api/reddit-events',
  );

  runApp(MyApp());
}

// Track a purchase anywhere in your app
await RedditPixel.instance.trackPurchase(
  value: 99.99,
  currency: 'USD',
  itemCount: 2,
  userData: RedditUserData(
    email: 'customer@example.com',
    externalId: 'user-123',
  ),
);

Advanced Usage #

Direct Mode (Development Only)

⚠️ Warning: Direct mode embeds your Reddit API token in the app binary. Use only for development.

await RedditPixel.initialize(
  pixelId: 'your-pixel-id',
  token: 'your-reddit-api-token',
  testMode: true,  // Events won't affect production data
  debug: true,     // Enable debug logging
);

Custom Identity Provider

To enable IDFA/AAID tracking, implement RedditIdentityProvider:

import 'package:advertising_id/advertising_id.dart';
import 'package:app_tracking_transparency/app_tracking_transparency.dart';

class AppIdentityProvider implements RedditIdentityProvider {
  @override
  Future<String?> getAdvertisingId() async {
    try {
      if (Platform.isIOS) {
        final status = await AppTrackingTransparency.trackingAuthorizationStatus;
        if (status != TrackingStatus.authorized) return null;
      }
      return await AdvertisingId.id(true);
    } catch (_) {
      return null;
    }
  }

  @override
  Future<bool> isTrackingEnabled() async {
    if (Platform.isIOS) {
      final status = await AppTrackingTransparency.trackingAuthorizationStatus;
      return status == TrackingStatus.authorized;
    }
    return true;
  }
}

// Use it during initialization
await RedditPixel.initialize(
  pixelId: 'your-pixel-id',
  proxyUrl: 'https://your-server.com/api/reddit-events',
  identityProvider: AppIdentityProvider(),
);

All Event Types

// Standard events
await RedditPixel.instance.trackPurchase(value: 99.99, currency: 'USD');
await RedditPixel.instance.trackSignUp();
await RedditPixel.instance.trackLead();
await RedditPixel.instance.trackAddToCart(value: 49.99, currency: 'USD');
await RedditPixel.instance.trackAddToWishlist(value: 199.99, currency: 'USD');
await RedditPixel.instance.trackSearch(searchString: 'wireless headphones');
await RedditPixel.instance.trackViewContent(contentId: 'product-123');
await RedditPixel.instance.trackPageVisit(pageUrl: '/checkout');

// Custom events
await RedditPixel.instance.trackCustom(
  'VideoWatched',
  customData: {'video_id': 'vid-123', 'duration': 120},
);

// Generic tracking with event objects
await RedditPixel.instance.track(
  PurchaseEvent(
    value: 99.99,
    currency: 'USD',
    userData: RedditUserData(email: 'user@example.com'),
  ),
);

Queue Management

// Get pending event count
final count = await RedditPixel.instance.pendingEventCount;

// Force immediate flush of queued events
await RedditPixel.instance.flush();

// Dispose when done (e.g., app termination)
await RedditPixel.instance.dispose();

API Reference #

RedditPixel #

Method Description
initialize() Initialize the library with configuration
track(event) Track any RedditEvent
trackPurchase() Track a purchase conversion
trackSignUp() Track a sign-up conversion
trackLead() Track a lead generation
trackAddToCart() Track add-to-cart action
trackAddToWishlist() Track add-to-wishlist action
trackSearch() Track a search action
trackViewContent() Track content view
trackPageVisit() Track page/screen visit
trackCustom() Track custom events
flush() Force send queued events
dispose() Release resources

RedditUserData #

Field Type Description
email String? User's email (hashed before sending)
externalId String? Your system's user ID (hashed)
uuid String? UUID for cross-device attribution
idfa String? iOS advertising ID (hashed)
aaid String? Android advertising ID (hashed)
ipAddress String? User's IP address
userAgent String? Browser/app user agent
clickId String? Reddit click ID (rdt_cid parameter)

Security #

PII Handling #

All personally identifiable information (PII) is automatically normalized and SHA-256 hashed before transmission:

  • Email: Trimmed, lowercased, then hashed
  • Phone: Normalized to digits only, then hashed
  • IDFA: Uppercased, then hashed
  • AAID: Lowercased, then hashed

Transport Security #

Mode Token Location Recommendation
Proxy Server-side only ✅ Production
Direct Embedded in app ⚠️ Development only

Issues #

Please file issues, bugs, or feature requests in our issue tracker.

Contributing #

If you wish to contribute, please review our contribution guidelines and open a pull request.

License #

This project is licensed under the BSD-3-Clause License - see the LICENSE file for details.


Made with ❤️ by TPN Labs

1
likes
150
points
48
downloads

Documentation

API reference

Publisher

verified publishertpn-labs.com

Weekly Downloads

A privacy-centric, backend-agnostic Flutter library for Reddit Conversions API (CAPI) v3. Supports direct and proxy transport modes with offline-first persistence.

Repository (GitHub)
View/report issues

License

BSD-3-Clause (license)

Dependencies

connectivity_plus, crypto, dio, flutter, hive, hive_flutter, meta, uuid

More

Packages that depend on reddit_pixel