larapixel-sdk
v1.3.1
Published
LaraPixel JavaScript SDK for event tracking and analytics
Maintainers
Readme
larapixel
LaraPixel - A powerful, lightweight JavaScript SDK for tracking events and user behavior with LaraPixel analytics platform.
🚀 Features
- 📊 Real-time Event Tracking - Trac## 🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🔗 Links
- 📦 NPM Package: https://www.npmjs.com/package/larapixel-sdk
- 🌐 GitHub Repository: https://github.com/emadrashad/larapixel
- 📚 Documentation: https://github.com/emadrashad/larapixel
- 🐛 Issues: https://github.com/emadrashad/larapixel/issues
📞 Support
- 📧 Email: [email protected]
- 💬 Discussions: https://github.com/emadrashad/larapixel
- 🐛 Bug Reports: https://github.com/emadrashad/larapixel/issues
Made with ❤️ by Emad Rashad
- 🌍 Platform Support - Works with multiple providers (Snapchat, TikTok, Facebook/Meta, Twitter, Google, LinkedIn, Pinterest, and custom providers)
- 🔄 Dynamic URL Configuration - Switch between environments on the fly
- 🛡️ Privacy Compliant - GDPR ready with Do Not Track support
- 📱 Lightweight - Under 15KB minified and gzipped
- ⚡ Fast & Reliable - Auto-retry failed events, offline support
- 🎯 Easy Integration - Just 2 lines of code to get started
- 🎛️ Manual Control - No automatic tracking, fire events only when you want
🔥 Important: Manual Tracking Only (v1.3.0+)
LaraPixel now defaults to manual tracking only. Nothing gets tracked automatically unless you explicitly call tracking methods:
const larapx = new LaraPixel({
trackingId: 'your-id',
provider: 'snapchat'
});
// ❌ No automatic tracking happens on initialization
// ✅ You control exactly when events are fired
larapx.track('PAGE_LOADED', { page_type: 'homepage' });
larapx.track('PURCHASE', { order_id: '12345', value: 99.99 });Want automatic tracking? You can optionally enable it:
larapx.enableAutoTracking({
pageViews: true,
pageLeave: true
});Installation
Via CDN (Recommended for most users)
<!-- Include the SDK -->
<script src="https://unpkg.com/@larapixel/sdk@latest/dist/larapixel.min.js"></script>
<!-- Configure and initialize (Multiple options) -->
<script>
// Option 1: LaraPixel (default provider)
window.larapxConfig = {
trackingId: 'your-tracking-id',
trackingToken: 'your-auth-token', // Optional token
provider: 'larapixel',
trackingUrl: 'https://your-domain.com/api/track'
};
// Option 2: Snapchat Pixel
window.larapxConfig = {
trackingId: 'your-snap-pixel-id',
trackingToken: 'snap-conversions-api-token',
provider: 'snapchat',
trackingUrl: 'https://your-domain.com/api/track',
providerConfig: {
snapchat: {
testMode: false // Only additional settings, not duplicating ID/token
}
}
};
// Option 3: TikTok Pixel
window.larapxConfig = {
trackingId: 'your-tiktok-pixel-id',
trackingToken: 'tiktok-events-api-token',
provider: 'tiktok',
trackingUrl: 'https://your-domain.com/api/track',
providerConfig: {
tiktok: {
testMode: false // Only additional settings
}
}
};
// Option 4: Facebook/Meta Pixel
window.larapxConfig = {
trackingId: 'your-fb-pixel-id',
trackingToken: 'fb-access-token',
provider: 'facebook',
trackingUrl: 'https://your-domain.com/api/track',
providerConfig: {
facebook: {
testEventCode: 'TEST12345' // Only additional settings for testing
}
}
};
</script>Via NPM
npm install @larapixel/sdkimport LaraPixel from '@larapixel/sdk';
// Option 1: LaraPixel (default provider)
const larapx = new LaraPixel({
trackingId: 'your-tracking-id',
provider: 'larapixel',
trackingUrl: 'https://your-domain.com/api/track'
});
// Option 2: Snapchat Pixel
const larapx = new LaraPixel({
trackingId: 'your-snap-pixel-id',
trackingToken: 'snap-conversions-api-token',
provider: 'snapchat',
trackingUrl: 'https://your-domain.com/api/track',
providerConfig: {
snapchat: {
testMode: false // Only additional settings
}
}
});
// Option 3: TikTok Pixel
const larapx = new LaraPixel({
trackingId: 'your-tiktok-pixel-id',
trackingToken: 'tiktok-events-api-token',
provider: 'tiktok',
trackingUrl: 'https://your-domain.com/api/track',
providerConfig: {
tiktok: {
testMode: false // Only additional settings
}
}
});
// Option 4: Multi-provider with custom headers
const larapx = new LaraPixel({
trackingId: 'your-fb-pixel-id',
trackingToken: 'fb-access-token',
provider: 'facebook',
trackingUrl: 'https://api.yourapp.com/track',
providerConfig: {
facebook: {
testEventCode: 'TEST12345' // Only additional settings
}
},
customHeaders: {
'Authorization': 'Bearer your-token',
'X-API-Version': 'v1'
}
});Quick Start
Basic Usage (CDN)
<!DOCTYPE html>
<html>
<head>
<!-- LaraPixel SDK -->
<script src="https://unpkg.com/@larapixel/sdk@latest/dist/larapixel.min.js"></script>
<script>
// Configuration (Manual tracking only - no auto-tracking)
window.larapxConfig = {
trackingId: 'your-tracking-id',
provider: 'larapixel',
trackingUrl: 'https://your-domain.com/api/track',
debug: true // Enable for development
// Note: autoTrack is disabled by default (manual control)
};
</script>
</head>
<body>
<h1>My Website</h1>
<button onclick="larapx.track('BUTTON_CLICK', { button: 'hero-cta' })">
Sign Up Now
</button>
<script>
// Manual tracking - you control when events fire
larapx.track('PAGE_LOADED', {
page_type: 'homepage',
user_type: 'visitor'
});
// Track button clicks manually
larapx.track('BUTTON_CLICK', {
button_id: 'hero-cta',
button_text: 'Sign Up Now'
});
// Identify users
larapx.identify('user_123', {
email: '[email protected]',
plan: 'premium'
});
// Optional: Enable auto-tracking if needed
// larapx.enableAutoTracking({ pageViews: true, pageLeave: true });
</script>
</body>
</html>Module Usage (NPM)
import LaraPixel from '@larapixel/sdk';
// Initialize (Manual tracking only by default)
const larapx = new LaraPixel({
trackingId: 'your-tracking-id',
provider: 'larapixel',
trackingUrl: 'https://your-domain.com/api/track',
debug: process.env.NODE_ENV === 'development'
});
// Manual event tracking - you control when events fire
larapx.track('PAGE_LOADED', {
page_type: 'homepage',
user_type: 'visitor'
});
larapx.track('PURCHASE', {
order_id: '12345',
value: 99.99,
currency: 'USD',
items: [
{ name: 'Product 1', price: 49.99 },
{ name: 'Product 2', price: 49.99 }
]
});
// Manual page view tracking
larapx.page({
category: 'product',
product_id: 'abc123'
});
// Identify users
larapx.identify('user_456', {
email: '[email protected]',
subscription: 'pro'
});
// Optional: Enable auto-tracking if you want automatic events
// larapx.enableAutoTracking({ pageViews: true, pageLeave: true });API Reference
Configuration Options
type ProviderType = 'larapixel' | 'snapchat' | 'tiktok' | 'facebook' | 'meta' | 'twitter' | 'google' | 'linkedin' | 'pinterest' | 'custom';
interface LaraPixelConfig {
trackingId: string; // Your tracking ID (required) - formerly pixelId
trackingToken?: string; // Optional tracking token for additional authentication
provider?: ProviderType; // Provider type (default: 'larapixel')
trackingUrl?: string; // Direct tracking endpoint
baseUrl?: string; // Base API URL (alternative to trackingUrl)
endpoints?: { // Custom endpoints (used with baseUrl)
track?: string; // Tracking endpoint (default: '/api/track')
snippet?: string; // Snippet endpoint (default: '/api/snippet.js')
};
debug?: boolean; // Enable debug logging (default: false)
respectDoNotTrack?: boolean; // Respect Do Not Track (default: true)
autoTrack?: { // Auto-tracking options (all default to FALSE now)
pageViews?: boolean; // Track page views (default: false - manual only)
pageLeave?: boolean; // Track page exits (default: false - manual only)
clicks?: boolean; // Track link/button clicks (default: false)
formSubmits?: boolean; // Track form submissions (default: false)
};
retryFailedEvents?: boolean; // Retry failed events (default: true)
maxRetries?: number; // Max retry attempts (default: 3)
retryInterval?: number; // Retry interval in ms (default: 30000)
customHeaders?: Record<string, string>; // Custom HTTP headers for requests
suppressSSRWarning?: boolean; // Suppress SSR environment warnings (default: false)
// Provider-specific configurations (additional settings only)
providerConfig?: {
larapixel?: { [key: string]: any };
snapchat?: { testMode?: boolean; apiVersion?: string };
tiktok?: { testMode?: boolean; apiVersion?: string };
facebook?: { testEventCode?: string; apiVersion?: string };
meta?: { testEventCode?: string; apiVersion?: string };
twitter?: { apiVersion?: string };
google?: { debugMode?: boolean; apiVersion?: string };
linkedin?: { apiVersion?: string };
pinterest?: { apiVersion?: string };
custom?: { [key: string]: any };
};
}Methods
track(eventType, eventData?, options?)
Track any custom event.
// Basic event
larapx.track('BUTTON_CLICK');
// Event with data
larapx.track('PURCHASE', {
order_id: '12345',
value: 99.99,
currency: 'USD'
});
// Event with options
larapx.track('SPECIAL_EVENT',
{ data: 'value' },
{ forceTrack: true, userId: 'custom_user_id' }
);page(properties?)
Track page views (called automatically if autoTrack.pageViews is enabled).
// Basic page view
larapx.page();
// Page view with properties
larapx.page({
category: 'blog',
article_id: 'how-to-track-events',
author: 'john_doe'
});identify(userId, properties?)
Identify a user and associate future events with them.
// Basic identification
larapx.identify('user_123');
// With user properties
larapx.identify('user_123', {
email: '[email protected]',
name: 'John Doe',
plan: 'premium',
signup_date: '2024-01-15'
});reset()
Reset user identification (useful for logout).
larapx.reset();configure(newConfig)
Update configuration at runtime.
larapx.configure({
debug: true,
respectDoNotTrack: false
});Header Management Methods
// Set custom headers (merged with defaults)
larapx.setHeader('X-Custom', 'value');
larapx.setHeaders({ 'X-App': 'myapp', 'X-Version': '1.0' });
// Get current custom headers
const customHeaders = larapx.getHeaders();
// Remove custom headers
larapx.removeHeader('X-Custom');
larapx.clearHeaders();
// Full header control (override mode)
larapx.setActualHeaders({
'Content-Type': 'application/json',
'Authorization': 'Bearer token'
});
// Update override headers
larapx.updateActualHeaders({ 'X-New': 'value' });
// Get all headers that will be sent
const allHeaders = larapx.getAllHeaders();
// Check override mode status
const isOverrideMode = larapx.isHeaderOverrideEnabled();
// Disable override mode
larapx.disableHeaderOverride();Provider Management Methods
// Get current provider
const provider = larapx.getProvider();
// Switch provider at runtime
larapx.setProvider('snapchat', {
testMode: false // Only additional settings
});
// Switch to TikTok
larapx.setProvider('tiktok', {
testMode: true // Only additional settings
});Token Management Methods
// Set or update tracking token
larapx.setTrackingToken('new-auth-token-123');
// Get current tracking token
const token = larapx.getTrackingToken();
// Example: Dynamic token refresh
async function refreshToken() {
const newToken = await fetchNewTokenFromAPI();
larapx.setTrackingToken(newToken);
}Auto-Tracking Control Methods
// Enable auto-tracking (disabled by default now)
larapx.enableAutoTracking({
pageViews: true,
pageLeave: true,
clicks: false,
formSubmits: false
});
// Enable all auto-tracking
larapx.enableAutoTracking();
// Disable auto-tracking
larapx.disableAutoTracking();Configuration Design
Why trackingId + trackingToken + providerConfig?
trackingId: The main identifier (pixel ID, measurement ID, etc.)trackingToken: The authentication token (API secret, access token, etc.)providerConfig: Only additional provider-specific settings (test mode, API version, etc.)
This approach eliminates redundancy and keeps the configuration clean:
// ✅ Clean approach
const larapx = new LaraPixel({
trackingId: 'snap-pixel-123', // Main ID
trackingToken: 'snap-api-token', // Auth token
provider: 'snapchat',
providerConfig: {
snapchat: {
testMode: false // Only additional settings
}
}
});
// ❌ Redundant approach (old way)
const larapx = new LaraPixel({
trackingId: 'snap-pixel-123',
trackingToken: 'snap-api-token',
provider: 'snapchat',
providerConfig: {
snapchat: {
pixelId: 'snap-pixel-123', // Redundant!
apiToken: 'snap-api-token', // Redundant!
testMode: false
}
}
});Common Provider Examples
Google Analytics 4
const larapx = new LaraPixel({
trackingId: 'G-XXXXXXXXXX',
trackingToken: 'measurement-protocol-api-secret',
provider: 'google',
trackingUrl: 'https://your-proxy.com/api/track',
providerConfig: {
google: {
debugMode: false // Only additional settings
}
}
});Snapchat Conversions API
const larapx = new LaraPixel({
trackingId: 'your-snap-pixel-id',
trackingToken: 'snap-conversions-api-token',
provider: 'snapchat',
trackingUrl: 'https://your-server.com/api/track',
providerConfig: {
snapchat: {
testMode: process.env.NODE_ENV === 'development' // Only additional settings
}
}
});TikTok Events API
const larapx = new LaraPixel({
trackingId: 'your-tiktok-pixel-id',
trackingToken: 'tiktok-events-api-access-token',
provider: 'tiktok',
trackingUrl: 'https://your-server.com/api/track',
providerConfig: {
tiktok: {
testMode: false // Only additional settings
}
}
});Multi-Provider Setup
// Initialize with primary provider
const larapx = new LaraPixel({
trackingId: 'primary-id',
trackingToken: 'primary-token',
provider: 'larapixel',
trackingUrl: 'https://your-server.com/api/track'
});
// Switch to different providers as needed
function switchToSnapchat() {
larapx.setProvider('snapchat', {
testMode: false // Only additional settings
});
larapx.setTrackingToken('snap-api-token');
}
function switchToTikTok() {
larapx.setProvider('tiktok', {
testMode: false // Only additional settings
});
larapx.setTrackingToken('tiktok-events-token');
}Common Event Types
E-commerce Events
// Purchase completed
larapx.track('PURCHASE', {
order_id: '12345',
value: 99.99,
currency: 'USD',
items: [
{ name: 'Product 1', price: 49.99, quantity: 1 },
{ name: 'Product 2', price: 49.99, quantity: 1 }
]
});
// Add to cart
larapx.track('ADD_TO_CART', {
product_id: 'abc123',
product_name: 'Cool T-Shirt',
price: 29.99,
quantity: 2
});
// Remove from cart
larapx.track('REMOVE_FROM_CART', {
product_id: 'abc123',
product_name: 'Cool T-Shirt'
});
// Begin checkout
larapx.track('BEGIN_CHECKOUT', {
cart_total: 99.99,
items_count: 3
});User Engagement Events
// Newsletter signup
larapx.track('NEWSLETTER_SIGNUP', {
email: '[email protected]',
source: 'footer_form'
});
// Video interaction
larapx.track('VIDEO_PLAY', {
video_title: 'Product Demo',
video_duration: 120,
video_position: 'homepage'
});
// File download
larapx.track('FILE_DOWNLOAD', {
file_name: 'pricing-guide.pdf',
file_type: 'pdf',
download_source: 'pricing_page'
});
// Search
larapx.track('SEARCH', {
query: 'red shoes',
results_count: 24,
page: 'search'
});Form Events
// Form submission
document.getElementById('contact-form').addEventListener('submit', function(e) {
larapx.track('FORM_SUBMIT', {
form_name: 'contact',
form_location: 'footer',
form_fields: ['name', 'email', 'message']
});
});
// Form field interaction
larapx.track('FORM_FIELD_FOCUS', {
field_name: 'email',
form_name: 'signup'
});Dynamic URL Configuration
Change URLs at Runtime
// Switch environments dynamically
larapx.setBaseUrl('https://staging-api.yourapp.com'); // Staging
larapx.setBaseUrl('https://api.yourapp.com'); // Production
// Change tracking URL directly
larapx.setTrackingUrl('https://backup-api.yourapp.com/track');
// Update full configuration
larapx.configure({
baseUrl: 'https://new-api.yourapp.com',
debug: true,
endpoints: {
track: '/v2/track'
}
});Environment Switching
// Development
const config = {
pixelId: 'px_dev_123',
baseUrl: 'http://localhost:8000',
debug: true
};
// Production
const config = {
pixelId: 'px_prod_123',
baseUrl: 'https://api.yourapp.com',
debug: false
};
larapx.configure(config);Failover Support
// Try primary server, fallback to backup
larapx.track('IMPORTANT_EVENT', eventData)
.catch(() => {
larapx.setTrackingUrl('https://backup-api.com/track');
return larapx.track('IMPORTANT_EVENT', eventData);
});Custom Headers
Configuration Headers
Set custom headers during initialization:
const larapx = new LaraPixel({
pixelId: 'your-pixel-id',
trackingUrl: 'https://api.yourapp.com/track',
customHeaders: {
'Authorization': 'Bearer your-token',
'X-Custom-Header': 'your-value',
'X-API-Version': 'v1'
}
});Dynamic Header Management
Manage headers at runtime for maximum flexibility:
// Set individual header
larapx.setHeader('Authorization', 'Bearer new-token');
larapx.setHeader('X-User-ID', '12345');
// Set multiple headers at once
larapx.setHeaders({
'X-Session-ID': 'session_abc123',
'X-Device-Type': 'mobile',
'Accept-Language': 'en-US'
});
// Get current headers
const headers = larapx.getHeaders();
console.log(headers);
// Remove specific header
larapx.removeHeader('X-Session-ID');
// Clear all custom headers
larapx.clearHeaders();Common Use Cases
Authentication Headers
// JWT token authentication
larapx.setHeader('Authorization', `Bearer ${userToken}`);
// API key authentication
larapx.setHeader('X-API-Key', 'your-api-key');User Context Headers
// User identification
larapx.setHeaders({
'X-User-ID': currentUser.id,
'X-User-Role': currentUser.role,
'X-Tenant-ID': currentUser.tenantId
});Request Metadata
// Device and app info
larapx.setHeaders({
'X-App-Version': '1.2.3',
'X-Platform': 'web',
'X-User-Agent-Info': navigator.userAgent,
'Accept-Language': navigator.language
});Dynamic Headers Based on State
// Update headers when user logs in
function onUserLogin(user) {
larapx.setHeaders({
'Authorization': `Bearer ${user.token}`,
'X-User-ID': user.id,
'X-Session-Start': new Date().toISOString()
});
}
// Clear sensitive headers on logout
function onUserLogout() {
larapx.removeHeader('Authorization');
larapx.removeHeader('X-User-ID');
}Full Header Control (Override Mode)
For complete control over HTTP headers, you can use the override mode:
// Set exact headers that will be sent (overrides all other headers)
larapx.setActualHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer your-token',
'x-source': 'web',
'x-app-token': 'your-app-token',
'x-tenant': 'your-tenant',
'User-Agent': 'LaraPixel/1.0'
});
// Update specific override headers
larapx.updateActualHeaders({
'Authorization': 'Bearer new-token',
'x-session-id': 'session-123'
});
// Check current override headers
console.log('Override headers:', larapx.getActualHeaders());
// Check all headers that will be sent
console.log('All headers:', larapx.getAllHeaders());
// Check if override mode is enabled
console.log('Override mode:', larapx.isHeaderOverrideEnabled());
// Disable override mode (return to normal header merging)
larapx.disableHeaderOverride();Override Mode vs Normal Mode
// Normal mode: Headers are merged (default + config + custom + dynamic)
larapx.setHeader('X-Custom', 'value'); // Adds to existing headers
// Override mode: Only specified headers are sent
larapx.setActualHeaders({ // Replaces ALL headers
'Content-Type': 'application/json',
'X-Custom': 'value'
});Use Cases for Override Mode
// 1. Strict API requirements
larapx.setActualHeaders({
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': `Bearer ${token}`,
'X-API-Version': 'v1'
});
// 2. Proxy or middleware requirements
larapx.setActualHeaders({
'Content-Type': 'application/json',
'X-Forwarded-For': clientIP,
'X-Real-IP': clientIP,
'X-Proxy-Authorization': proxyToken
});
// 3. Multi-tenant applications
larapx.setActualHeaders({
'Content-Type': 'application/json',
'x-tenant': currentTenant,
'x-app-token': tenantToken,
'x-source': 'web'
});Advanced Features
Queue Events Before Initialization
Events can be tracked even before the SDK loads:
<script>
// This works immediately, even before SDK loads
window.larapx = window.larapx || [];
window.larapx.push(['track', 'EARLY_EVENT', { timestamp: Date.now() }]);
</script>Error Handling
larapx.track('MY_EVENT', { data: 'value' })
.then(response => {
console.log('Event tracked successfully:', response);
})
.catch(error => {
console.error('Failed to track event:', error);
// Event is automatically queued for retry
});Privacy Compliance
The SDK respects user privacy preferences:
// Automatically respects "Do Not Track" browser setting
// Can be overridden per event:
larapx.track('CRITICAL_EVENT',
{ data: 'value' },
{ forceTrack: true } // Ignores Do Not Track for this event
);Custom User IDs
// Use your own user IDs
larapx.track('EVENT', {}, { userId: 'my_custom_user_id' });
// Or set globally
larapx.identify('my_custom_user_id');Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
- IE 11+ (with polyfills)
Migration Guide
Upgrading from v1.2.x to v1.3.0+
⚠️ Breaking Changes:
pixelIdrenamed totrackingId- Auto-tracking disabled by default
// ❌ Old way (v1.2.x)
const larapx = new LaraPixel({
pixelId: 'px_123', // Old name
trackingUrl: 'https://api.com/track'
// Auto-tracking was enabled by default
});
// ✅ New way (v1.3.0+)
const larapx = new LaraPixel({
trackingId: 'px_123', // New name
provider: 'larapixel', // New: specify provider
trackingUrl: 'https://api.com/track'
// Auto-tracking is now disabled by default
});
// If you want auto-tracking, enable it explicitly
larapx.enableAutoTracking({
pageViews: true,
pageLeave: true
});TypeScript Support
The SDK includes full TypeScript definitions:
import LaraPixel, { LaraPixelConfig, EventData, ProviderType } from '@larapixel/sdk';
const config: LaraPixelConfig = {
trackingId: 'your-tracking-id',
trackingToken: 'your-auth-token',
provider: 'snapchat' as ProviderType,
trackingUrl: 'https://api.example.com/track',
debug: true,
providerConfig: {
snapchat: {
testMode: false
}
}
};
const larapx = new LaraPixel(config);
const eventData: EventData = {
product_id: 'abc123',
value: 99.99
};
// Manual tracking only (no auto-tracking by default)
larapx.track('PURCHASE', eventData);
// Optional: Enable auto-tracking if needed
larapx.enableAutoTracking({ pageViews: true });Troubleshooting
Events Not Appearing
- Check browser console for errors
- Verify
pixelIdandtrackingUrlare correct - Enable debug mode:
debug: true - Check network tab for failed requests
- Verify CORS settings on your server
Ad Blockers
The SDK includes retry mechanisms and fallbacks for ad blocker compatibility. Failed events are automatically queued and retried.
GDPR Compliance
- Respects "Do Not Track" by default
- No cookies are set (uses localStorage/sessionStorage)
- Users can be identified only when explicitly called
- All data collection can be disabled
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE file for details.
Support
- 📧 Email: [email protected]
- 📚 Documentation: https://github.com/emadrashad/LaraPixel
- 🐛 Issues: https://github.com/emadrashad/LaraPixel/issues
