How we automatically share new content on social media

Published on by

How we automatically share new content on social media image

When we publish a new post here on Laravel News, many things happen in the background for it to be automatically sent out to all the places around the internet. In this post, let's look at how we share it with all the services.

Here is a basic flowchart of what happens on Laravel News when a post is published showing all the services involved:

As you can see, we utilize many different services, but once they are set up, it's not something we've had too much trouble with, and it all happens automatically.

Starting from left to right, let's go through each section and cover how it's setup:

Laravel Notification Channels

Laravel Notification Channels are fantastic, and the community has created many different providers for use. We utilize one for our Twitter account, and another for our read-only Telegram account.

For Telegram, we have an older, but still accurate write-up on auto publishing to Telegram

Here is the code for our PostPublished notification:

class PostPublished extends Notification
{
public function via($notifiable)
{
return [TelegramChannel::class, TwitterChannel::class];
}
 
public function toTelegram($post)
{
return TelegramMessage::create()
->to('@laravelnews')
->content($post->routes['title'].' https://laravel-news.com/'.$post->routes['uri']);
}
 
public function toTwitter($post)
{
$tweet = $post->routes['title'].' https://laravel-news.com/'.$post->routes['uri'];
if ($post->routes['category'] == 'sponsor') {
$tweet = $post->routes['title'].' [SPONSOR] https://laravel-news.com/'.$post->routes['uri'];
} else if ($handle = $this->twitterHandle($post->routes['twitter_handle'])) {
$tweet = $tweet.' posted by '.$handle;
}
return new TwitterStatusUpdate($tweet);
}
 
/**
* Add the twitter handle is they are not a mod.
*/
protected function twitterHandle($twitter)
{
if (! $twitter) {
return false;
}
 
if ($twitter and ! Str::startsWith($twitter, '@')) {
$twitter = '@'.$twitter;
}
 
return $twitter;
}
}

Emails

We have two primary email lists. One is sent every day, and it includes any new posts and new community links. Then a second list for a weekly email that is sent every Sunday that is currently manually built. You can subscriber to them on our Newsletter page.

The daily is entirely automated and how it works is by utilizing a scheduled console command that queries our Statamic backend for new posts and builds out a complete HTML email in a blade file. From this, we use the Campaign Monitor API to create a draft, then instantly send the email.

protected function schedule(Schedule $schedule)
{
$schedule->command('ln:daily')->daily()->at('15:00');

Here is the code for doing the actual sending...

protected function sendEmail($posts)
{
$auth = ['api_key' => config('services.campaign-monitor.key')];
$cm = new CS_REST_Campaigns(null, $auth);
 
// Create a draft from the API
$draft = $cm->create(config('services.campaign-monitor.client_id'), [
'Subject' => $posts[0]['title']->raw(), // first post of the day, usually only one.
'Name' => 'Laravel News Daily ('.date('Y-m-d').')',
'FromName' => 'Laravel News',
'FromEmail' => 'hello@laravel-news.com',
'ReplyTo' => 'hello@laravel-news.com',
'HtmlUrl' => '/full/path/to/daily/html/file',
'ListIDs' => [config('services.campaign-monitor.daily_id')],
]);
 
// grab the draft id and set it to the campaign
$cm->set_campaign_id($draft->response);
 
// now send it
$cm->send([
'ConfirmationEmail' => 'hello@laravel-news.com',
'SendDate' => 'immediately',
]);
}

RSS Feed

The RSS feed is manually built using the same method as outlined in our tutorial on creating an RSS feed from scratch, but we take it a step further and use a 3rd party service named Feedpress.

By using the third party, we get some stats around RSS readership, which, in theory, is beneficial but not something we check very often.

RSS to Zapier

The next main section utilizes Zapier to read from new items in an RSS feed, then sends the post off to other services.

Facebook and LinkedIn Zaps both get sent to Buffer and then shared from Buffer. We initially used Buffer here because our community links section can have many approved on the same day at the same time, so instead of sharing all those at once, we can utilize more fine-grained scheduling.

For the Mastodon part, I used this tutorial a few weeks ago, and it's been running smoothly since.

JSON Feed

JSON Feeds was a hot topic a few years ago, so we had to have it. This is pretty simple to build, and we have a full tutorial on generating a JSON feed here.

Google News Feed

The final feed is for Google News, which was tricky to set up because they have a lot of restrictions on what they consider news and if you share something to this that they don't consider news, they can block you.

The basics of submitting are you need to give them a special XML feed, but it can only have items published in the past two days and can only be news items.

Here is our controller for setting up all this data from our Statamic backend:

public function news()
{
$posts = Collection::find('articles')
->queryEntries()
->where('date', '>', Carbon::now()->subDays(2)->startOfDay())
->where('date', '<', Carbon::now())
->where('published', true)
->get()
->toAugmentedArray();
 
return response()->view('sitemap.google.news', [
'posts' => $posts,
])->header('Content-Type', 'text/xml');
}

Then the Blade view file:

<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:news="http://www.google.com/schemas/sitemap-news/0.9">
 
@foreach ($posts as $post)
<url>
<loc>{{ $post['permalink'] }}</loc>
<news:news>
<news:publication>
<news:name>Laravel News</news:name>
<news:language>en</news:language>
</news:publication>
<news:genres>Blog</news:genres>
<news:publication_date>{{ $post['date']->raw()->format("Y-m-d") }}</news:publication_date>
<news:title>{{ $post['title'] }}</news:title>
@if ($post['tag']->raw())
<news:keywords>{{ implode(',', $post['tag']->raw()) }}</news:keywords>
@endif
<news:stock_tickers></news:stock_tickers>
</news:news>
</url>
@endforeach
</urlset>

Closing

This is how we share with many different services when a new post is published. This setup has been in production for almost a decade and has been solid. While writing this out, I noticed how we could possibly simplify some of these because of newer Notification Channels and could remove the Buffer step totally. Of course, one could also use various APIs directly, but I've found going through Zapier passes on API changes to them instead of something I need to worry about.

If you'd like to follow us at any of the services mentioned, here are our pages:

Eric L. Barnes photo

Eric is the creator of Laravel News and has been covering Laravel since 2012.

Cube

Laravel Newsletter

Join 40k+ other developers and never miss out on new tips, tutorials, and more.

image
Paragraph

Manage your Laravel app as if it was a CMS – edit any text on any page or in any email without touching Blade or language files.

Visit Paragraph
Laravel Forge logo

Laravel Forge

Easily create and manage your servers and deploy your Laravel applications in seconds.

Laravel Forge
Tinkerwell logo

Tinkerwell

The must-have code runner for Laravel developers. Tinker with AI, autocompletion and instant feedback on local and production environments.

Tinkerwell
No Compromises logo

No Compromises

Joel and Aaron, the two seasoned devs from the No Compromises podcast, are now available to hire for your Laravel project. ⬧ Flat rate of $7500/mo. ⬧ No lengthy sales process. ⬧ No contracts. ⬧ 100% money back guarantee.

No Compromises
Kirschbaum logo

Kirschbaum

Providing innovation and stability to ensure your web application succeeds.

Kirschbaum
Shift logo

Shift

Running an old Laravel version? Instant, automated Laravel upgrades and code modernization to keep your applications fresh.

Shift
Bacancy logo

Bacancy

Supercharge your project with a seasoned Laravel developer with 4-6 years of experience for just $2500/month. Get 160 hours of dedicated expertise & a risk-free 15-day trial. Schedule a call now!

Bacancy
Lucky Media logo

Lucky Media

Bespoke software solutions built for your business. We ♥ Laravel

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel E-Commerce

E-Commerce for Laravel. An open-source package that brings the power of modern headless e-commerce functionality to Laravel.

Lunar: Laravel E-Commerce
LaraJobs logo

LaraJobs

The official Laravel job board

LaraJobs
Larafast: Laravel SaaS Starter Kit logo

Larafast: Laravel SaaS Starter Kit

Larafast is a Laravel SaaS Starter Kit with ready-to-go features for Payments, Auth, Admin, Blog, SEO, and beautiful themes. Available with Vue and Livewire stacks.

Larafast: Laravel SaaS Starter Kit
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit: Laravel SaaS Starter Kit

SaaSykit is a Laravel SaaS Starter Kit that comes with all features required to run a modern SaaS. Payments, Beautiful Checkout, Admin Panel, User dashboard, Auth, Ready Components, Stats, Blog, Docs and more.

SaaSykit: Laravel SaaS Starter Kit
Rector logo

Rector

Your partner for seamless Laravel upgrades, cutting costs, and accelerating innovation for successful companies

Rector

The latest

View all →
Asserting a JSON Response Structure in Laravel image

Asserting a JSON Response Structure in Laravel

Read article
Backpack turns 8 years old, celebrates with 40% discount image

Backpack turns 8 years old, celebrates with 40% discount

Read article
Create a DateTime from a Timestamp With this New Method Coming to PHP 8.4 image

Create a DateTime from a Timestamp With this New Method Coming to PHP 8.4

Read article
Neovim Plugin to for Navigating Laravel and Livewire Components image

Neovim Plugin to for Navigating Laravel and Livewire Components

Read article
Laravel Herd v1.7 is out with updates to the dump UI image

Laravel Herd v1.7 is out with updates to the dump UI

Read article
Share Error Package for Laravel's New Exception Page image

Share Error Package for Laravel's New Exception Page

Read article