Automating Social Sharing: Integrating LinkedIn Publishing in Laravel

The 'landing' project recently received an upgrade aimed at streamlining our content distribution. The goal was to automatically publish newly released blog posts to LinkedIn, enhancing our reach and ensuring our audience on professional networks stays informed. This update focuses on an event-driven approach using Laravel's powerful ecosystem.

The Challenge: Seamless LinkedIn Integration

Manually sharing every new blog post across social platforms can be a time-consuming task. We sought to automate this process for LinkedIn, ensuring that once a post is marked as published on our platform, it automatically appears on our company's LinkedIn page. This required a robust and scalable solution that wouldn't block the main application flow.

The Solution: Observers and Queued Jobs

Our approach leverages Laravel's Observer pattern and queued Jobs. When a Post model is updated and published, a PostObserver catches this event. Instead of directly interacting with the LinkedIn API within the observer, which could be slow and error-prone, it dispatches a dedicated job to the queue.

The Post Observer

The PostObserver acts as a listener for events on the Post model. Specifically, it can detect when a post's status changes to 'published'.

namespace App\Observers;

use App\Models\Post;
use App\Jobs\PublishPostToLinkedin;

class PostObserver
{
    public function updated(Post $post)
    {
        if ($post->isPublished() && $post->isDirty('status')) {
            PublishPostToLinkedin::dispatch($post);
        }
    }
}

In this example, the updated method checks if the post has just been published (i.e., its status changed to published). If so, it dispatches the PublishPostToLinkedin job, passing the Post instance.

The LinkedIn Publishing Job

The PublishPostToLinkedin job is where the actual interaction with the LinkedIn API occurs. By running this in a queue, we ensure that API calls don't block user requests, and we can retry failed attempts if needed. The job is responsible for formatting the post content, making the API request, and then storing the resulting LinkedIn post URL back in our database.

namespace App\Jobs;

use App\Models\Post;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Http;

class PublishPostToLinkedin implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $post;

    public function __construct(Post $post)
    {
        $this->post = $post;
    }

    public function handle()
    {
        // Placeholder for actual LinkedIn API logic
        $response = Http::post('https://api.linkedin.com/v2/ugcPosts', [
            'author' => 'urn:li:organization:your-org-id',
            'lifecycleState' => 'PUBLISHED',
            'specificContent' => [
                'com.linkedin.ugc.ShareContent' => [
                    'shareCommentary' => [
                        'text' => $this->post->title . ' - Read more: ' . url('/posts/' . $this->post->slug)
                    ],
                    'shareMediaCategory' => 'ARTICLE'
                ]
            ],
            'visibility' => [
                'com.linkedin.ugc.MemberNetworkVisibility' => 'PUBLIC'
            ]
        ]);

        if ($response->successful()) {
            $this->post->linkedin_post_url = $response->header('Location'); // Or parse actual ID
            $this->post->save();
        }
    }
}

This job fetches the post's title and URL, constructs a basic share payload, and sends it to the LinkedIn API. Upon success, it updates the linkedin_post_url column in the posts table, providing a direct link to the published LinkedIn post for tracking.

Data Persistence and Display

To support this integration, a linkedin_post_url column was added to the posts table. This allows us to store the direct URL to the published LinkedIn post. Furthermore, our PostResource and relevant UI components were updated to display this URL, providing administrators with immediate access to the shared content on LinkedIn.

The Outcome

By leveraging Laravel's event system and queueing capabilities, we've established an efficient and reliable mechanism for cross-posting content to LinkedIn. This reduces manual effort, ensures timely sharing, and maintains data integrity by storing the LinkedIn post URL directly with our content.

Actionable Takeaway

When building integrations with external APIs in Laravel, consider using Observers to react to model changes and Queued Jobs to handle the asynchronous API interactions. This pattern keeps your application responsive, provides fault tolerance through retries, and decouples complex external processes from your core application logic.

Automating Social Sharing: Integrating LinkedIn Publishing in Laravel
GERARDO RUIZ

GERARDO RUIZ

Author

Share: