Installation
composer require croct/plug-php
Add the Croct service provider to config/app.php under providers:
Croct\Plug\PlugServiceProvider::class,
Configuration Publish the config file:
php artisan vendor:publish --provider="Croct\Plug\PlugServiceProvider" --tag="config"
Update .env with your Croct API credentials:
CROCT_API_KEY=your_api_key_here
CROCT_API_SECRET=your_api_secret_here
First Use Case: Fetching Dynamic Content
Inject the Croct\Plug\PlugClient into a controller or service:
use Croct\Plug\PlugClient;
public function __construct(private PlugClient $croct)
{
}
public function show()
{
$content = $this->croct->content()->get('your-content-id');
return view('your.view', ['content' => $content]);
}
Key Documentation
content(), user(), and event() methods for core functionality.Dynamic Content Injection
Use PlugClient::content() to fetch personalized content by ID or slug:
$content = $croct->content()->get('homepage-hero');
Cache responses for performance:
$content = Cache::remember("croct_{$contentId}", now()->addHours(1), fn() =>
$croct->content()->get($contentId)
);
Content Fallbacks Handle missing content gracefully:
try {
$content = $croct->content()->get('promo-banner');
} catch (\Croct\Plug\Exceptions\ContentNotFoundException $e) {
$content = null; // Fallback to static content
}
Track and Identify Users
Associate users with Croct via their ID (e.g., Laravel’s auth()->id()):
$croct->user()->identify($userId, [
'email' => $user->email,
'name' => $user->name,
]);
Use middleware to auto-identify users on authenticated routes:
public function handle($request, Closure $next)
{
if (auth()->check()) {
app(PlugClient::class)->user()->identify(auth()->id());
}
return $next($request);
}
User Attributes Update user attributes dynamically (e.g., after checkout):
$croct->user()->setAttributes([
'plan' => 'premium',
'last_purchase' => now()->toDateTimeString(),
]);
$croct->event()->track('product_viewed', [
'product_id' => $product->id,
'category' => $product->category,
]);
Integrate with Laravel’s Event facade for consistency:
event(new \Croct\Plug\Events\UserViewedProduct($product));
Blade::directive('croct', function ($expression) {
return "<?php echo app(\Croct\Plug\PlugClient::class)->content()->render($expression); ?>";
});
Usage in Blade:
@croct('homepage-hero')
Service Container Binding
Bind PlugClient to the container for easier dependency injection:
$this->app->bind(PlugClient::class, function ($app) {
return new PlugClient(
$app['config']['croct.api_key'],
$app['config']['croct.api_secret']
);
});
Queueing Async Requests Offload Croct calls to queues to avoid blocking requests:
dispatch(new \Croct\Plug\Jobs\TrackEventJob($eventData));
Middleware for Auto-Tracking Create middleware to track page views automatically:
public function handle($request, Closure $next)
{
app(PlugClient::class)->event()->track('page_view', [
'url' => $request->url(),
'referrer' => $request->header('referer'),
]);
return $next($request);
}
Batch Content Requests Fetch multiple content items in a single request:
$contents = $croct->content()->batch(['hero', 'sidebar', 'footer']);
Local Caching Cache Croct responses with tags for invalidation:
Cache::tags(['croct-content'])->put("croct_{$contentId}", $content, now()->addMinutes(5));
API Rate Limits
try {
$content = $croct->content()->get($id);
} catch (\Croct\Plug\Exceptions\RateLimitExceededException $e) {
sleep($e->retryAfter);
retry();
}
User Identification Leaks
Log::withoutOverwrite() or sanitize logs:
Log::withoutOverwrite(function () use ($userId) {
Log::error("Failed to fetch content for user: " . str_replace($userId, '[REDACTED]', $userId));
});
Content ID Mismatches
'home-hero' vs. 'home_hero') will return ContentNotFoundException.enum ContentId: string {
case HOME_HERO = 'home_hero';
case FOOTER = 'footer';
}
Async Event Tracking Delays
event()->fire() for critical events and queue non-critical ones.Enable Debug Mode
Set CROCT_DEBUG=true in .env to log API requests/responses:
CROCT_DEBUG=true
CROCT_LOG_LEVEL=debug
Common Errors
| Error | Cause | Fix |
|---|---|---|
InvalidApiKeyException |
Wrong CROCT_API_KEY |
Check .env and regenerate keys in Croct dashboard. |
ContentNotFoundException |
Incorrect content ID | Verify IDs in Croct dashboard. |
NetworkTimeoutException |
Croct API unreachable | Check network connectivity; retry with backoff. |
JsonException |
Malformed response | Update the SDK (composer update croct/plug-php). |
Testing Locally
PlugClient in tests:
$mock = Mockery::mock(PlugClient::class);
$mock->shouldReceive('content->get')
->with('test-id')
->andReturn(['title' => 'Test']);
$this->app->instance(PlugClient::class, $mock);
Custom Content Renderers
Extend the Croct\Plug\Renderers\ContentRenderer to transform responses:
class CustomRenderer extends ContentRenderer {
public function render(array $content): string
{
// Custom logic (e.g., add tracking pixels)
return parent::render($content) . '<img src="tracker.png">';
}
}
Bind it in a service provider:
$this->app->bind(\Croct\Plug\Renderers\ContentRenderer::class, function () {
return new CustomRenderer();
});
Webhook Handlers Croct supports webhooks for real-time updates. Create a Laravel route:
Route::post
How can I help you explore Laravel packages today?