Gregory's Blog

Galaxie Blog Winter Update and Roadmap

Galaxie Blog Update

What is Galaxie Blog?

Galaxie Blog is the most modern and functional open-sourced Coldfusion Blog in the world. Galaxie Blog is a free open source ColdFusion blog platform, has an HTML5 interface, and is a beautifully designed responsive site that works flawlessly on desktop or mobile.

Galaxie Blog is completely open-source!

Galaxie Bog is open-source. All of the functionality out of the box that you see here is free. Unlike other blog software; I will commit to providing full functionality without charging any upcharge fee for more advanced features.

The only exception to this is that the blog owner may want to purchase their own Kendo license to include certain Kendo professional widgets- such as the Kendo grid. Galaxie Blog supports both the open-source version of Kendo Core, or Kendo Professional- which requires a license. The blog owner may choose to purchase their own professional Kendo UI license, directly from Telerik, to unlock certain Kendo UI functionality, such as incorporating the Kendo UI Grid.

So far, I have incorporated open-source libraries from third parties (such as Kendo Core), but I may eventually add a few more Kendo UI features that may require the professional license directly from Telerik. However, when I do decide to incorporate Kendo widgets requiring a paid license; I will always seek to provide similar free open-source functionality by developing free alternative interfaces.

Everything that you see on this blog, other than the grid that is shown below, is free and open-sourced. Grid, or no grid- this is a license thing that's totally up to you. I am not affiliated with Telerik- and will not be receiving any compensation.

Current Status

I am currently working on re-architecting Galaxie Blog to use ColdFusion ORM. Without getting into the weeds of the technical details, ColdFusion ORM allows Galaxie Blog to support any modern database. This is a massive endeavor! All of the database-oriented logic needs to be completely redone. I am also working on helping several clients migrating to Galaxie Blog. I likely will not have a new version of Galaxie Blog out until the early spring of 2020 (on a side note- I likely won't be blogging as much in the next few months).

Tentative 2020 General Roadmap (subject to change of course)

Version Date Description
1.75 Winter 2020 Re-engineer Galaxie Blog to use ColdFusion ORM. This will allow the blog owner to use Galaxie Blog with any modern database platform.
2.0 Spring 2020 Completely overhaul the administative interface and develop new HTML5 administrative interface that works with mobile devices
2.25 Summer 2020 Add functionality and rich editor widgets to the administative interface. It's my goal to be able to post a picture or a video along with a blog post using my mobile device. I'm currently investigating incorporating either TinyMce or CkEditor to allow blog owners and commenters to better present their posts.
2.50 Fall 2020 Develop Galaxie Blog into a Progressive Web Application.
3.0 Winter 2020 Incorporate ColdBox and Vue. ColdBox is the most popular ColdFusion MVC framework, and ColdBox has a much better ORM implementation. I am also really excited to use Vue (and ditch jQuery, which I am currently using). Vue should speed up the interative development cycles and make the code more maintainable.
TBD TBD Galaxie Blog supports two commenting systems, the native Galaxie Blog interface, and Disqus. However, the native Galaxie Blog interface does not have all of the features available in Disqus. It's my goal to make the core functionality of the native commenting interface comparable to the interfaces provided by Disqus. This requires having the blog handle Facebook and Twitter API logins.
TBD TBD Themes, themes, themes... Galaxie Blog already has dozens of professionally designed themes, but I will add a lot more. I'll also add the capability of attaching a theme to a blog post, a page, and potentially a widget. I also want to implement a theme pack- for example, to automatically display pictures of the current holiday or event- i.e. Halloween or Christmas. Although this is not what most users would think about when addressing blog functionality, it is really a fun feature and it improves user satisfaction.

Here is a fun little fact- did you know that Ben Nadel, one of the most pre-eminent ColdFusion bloggers around, coded his site to allow the user to always choose to display a certain photo when viewing his website? Ben's major theme is that he takes pictures with someone unique on most of his blog posts, and his readers can select to always view their own picture! Fun!
TBD TBD Improve user engagement. One of the biggest issues with blogging is that the users will read your posts, however, they rarely, if ever, comment or provide feedback. I will develop an interface to allow any user, even if they are not logged in, to recommend and or rate an article. Feedback is paramount to a successful blogger, and there is not really a good good mechanism to allow quick feedback right now other than to go through the captcha process and make a comment.
TBD TBD Enhance and develop new mobile interfaces. Currently, Galaxie Blogs Plyr control can cast video from the iPhone to an enabled airplay device for example, but I want to develop new interfaces improving native Andriod and iPhone functionality.
TBD TBD Better code syntax highlighting. Currently I use an older Java based library created by Jason Delmore to wrap up the code in a GUI, but there are other more modern open-source libraries such as Prism.

Note: this list is not complete, but represent some of the major milestones and goals that I want to incorporate into Galaxie Blog in the coming year.

If you would like to suggest any new features, or just make a general comment; please feel free to do so! I could always use any feedback or additional help!

I hope that everyone had a good holiday season- Happy Hanukkah, Merry Christmas, and all that jazz!

This entry was posted on January 15, 2020 at 6:35 PM and has received 155 views.

Playing your own video content with Galaxie Blog


How to integrate your own video content to Galaxie Blog

Galaxie Blog supports the following video types: .mp3 , .mp4, .ogg, .ogv and .webm. If you have the video in another legacy format, you'll need to convert it to a modern format to play it in Galaxie Blog.

If you have a supported video format, you can either upload the video by clicking on the Add Enclosure, or by using the file uploader in the Galaxie Blog administrative interface. However, the Add Enclosure method will only work if the video is smaller than around 3MB.. You can use your own FTP tools to upload the video if that is what you prefer.

You can also host videos that are stored on a different server, but you'll need to specify the cross-origin true argument using a Galaxie Blog Post Directive.

Though completely optional, if you want the video's to be optimized for different client devices, just like responsive images, you can use up to three videos with different sizes. Galaxie Blog supports 576p, 720p, and High Definition 1080p video formats.

Once you have the video(s) on a server, you will need to use the proper URL xml post directives

The following Galaxie Blog Post XML Directives were used to play the video that you see on top of this blog post.

  • The videoType directive is necessary. Here I set it to ".mp4"
  • The videoPosterImageUrl directive completely optional. This is used to 'cover' the video with an image until it is played. I used an image of the video to cover the video and specified the URL.
  • Since my video format is 720p, I used the mediumVideoSourceUrl directive.
    • You can use one argument, two, or all three to have a responsive video. You will need at least one argument for the video to play
    • Use smallVideoSourceUrl for 576p
    • Use mediumVideoSourceUrl for 720p
    • Use largeVideoSourceUrl for 1080p
    • Or use all three arguments if you want the video to be responsive
      • This video is hosted on the same domain, so I used false for the cross-origin argument. If you are integrating a video that is hosted on another server, set the videoCrossOrigin to true.

This snippet of code will initialize our Plyr and it will play the video file within Galaxie Blog. The video will be lazy loaded, and will only load once the page loads and the video is downloaded to the client.

As with all Galaxie Blog video's, the video will automatically play when your looking at an individual post, and requires the user to click on the play button when your looking at the post from the main blog page. You can easily change this behavior by editing the code, or by making a suggestion here.

Note: the xml post directives will be deprecated in a later version

This entry was posted on December 16, 2019 at 1:32 PM and has received 144 views.

Embedding a Video from Vimeo in Galaxie Blog


It is trivial to embed a video in your blog post from Vimeo using Galaxie Blog.

Simply grab the video Id from Vimeo, and copy and paste the id into the vimeo video xml post directive like so:

view plain about
1<postData>
2<vimeoVideoId:343068761></vimeoVideoId>
3</postData>

This snippet of code will initialize our Plyr and it will play the vimeo video file within Galaxie Blog. The video will be lazy loaded, and will only load once the page loads and the video is downloaded to the client.

As with all Galaxie Blog video's, the video will automatically play when your looking at an individual post, and requires the user to click on the play button when your looking at the post from the main blog page. You can easily change this behavior by editing the code, or by making a suggestion here.

Note: the xml post directives will be deprecated in a later version

This entry was posted on December 15, 2019 at 9:02 PM and has received 106 views.

Embedding a video from YouTube in Galaxie Blog


Just like Vimeo, you can embed a YouTube video easily with Galaxie Blog.

Simply grab the video URL from YouTube, and copy and paste the URL into the YouTube URL xml post directive like so:

This snippet of code will initialize our Plyr and it will play the YouTube video file within Galaxie Blog. The video will be lazy loaded, and will only load once the page loads and the video is downloaded to the client.

view plain about
1<postData>
2<youTubeUrl:https://www.youtube.com/watch?v=LXt-hDDiEAQ&feature=youtu.be></youTubeUrl>
3</postData>

This video is an amazing performance by Chris Botti and Carolyn Campbell playing Kashmir to the violin. The video source is from You Tube at https://www.youtube.com/watch?v=LXt-hDDiEAQ&feature=youtu.be.

As with all Galaxie Blog video's, the video will automatically play when your looking at an individual post, and requires the user to click on the play button when your looking at the post from the main blog page. You can easily change this behavior by editing the code, or by making a suggestion here.

Note: the xml post directives will be deprecated in a later version

This entry was posted on December 15, 2019 at 8:12 PM and has received 119 views.

Galaxie Blog XML Post Directives


Background

For those who don't know, Galaxie Blog was built on top of BlogCfc, one of the most popular ColdFusion Blog engines around. However, BlogCfc was originally built in the early 2000's.

Raymond Camden, the author of BlogCfc, used .ini files to store a lot of variable settings. It was a decent approach as the blog software in those days was much simpler. It is easier to store dynamic information in the .ini files rather than the database as BlogCfc supported SQL Server, MySql, Oracle and Access.

I also put quite a bit of information into the .ini files. In fact, I have nearly 500 different variables stuffed into the .ini files as putting it into a database was cumbersome as a lot of extra code and testing was required to support all of the databases.

However, using the .ini files to store a large amount of data is quite inefficient and slow.

After releasing version 1.15, I put a freeze on using any new settings into the .ini files. It was just too inefficient. It is my plan to wait until I get ColdFusion ORM up and running, and until then, I am either hardcoding some of the new variable information, and expanded on the existing BlogCfc XML Post Directives that I put in a Blog post.

What is a Galaxie Blog XML Post Directive?

BlogCfc used what I call a XML Post Directive to deliver certain functionality to a given blog post, such as wrapping a code block with <code> tags to present code. BlogCfc also used the <more/> tag to condense a post on the main site that aborted the page at a certain position and created a button that navigates the reader to the full post.

Since Galaxie Blog 1.15, I used a handful of additional XML Post Directives to embed optional meta tag information, such as embedding video, and to bypass ColdFusions' Global Script Protection that is used by my hosting provider. Once I integrate ORM, I'll eventually use an interface and code editor to do this without the XML Post Directives, but in the meantime I am using this approach.

Note: all of these directives are optional and only needed for certain occasions, such as including a video, to present video or code, and to bypass ColdFusions' Global Script Protection that is used by various ColdFusion hosting providers.

Original BlogCfc XML Post Directives

  • Use <code> tags to format programming code:
    1. Create the initial <code> tag.
    2. Insert the actual code
    3. Terminate your code block with </code>
  • Use a single <more/> tag to condense the blog body when you're looking at all of the blog posts:
    • Place a <more/> tag where you want the body to terminate
  • Real world example: Scoll down to Kendo Server Side Validation

SEO XML Post Directives

  • Set the meta title for the individual blog post:
    • Enter the title after titleMetaTag: string:
    • <titleMetaTag:Galaxie Blog Post Directives>
    • Terminate the tag with a closing </titleMetaTag>
  • Set the description for the individual blog post. This also sets the description when sharing the post on social media sites (i.e. the open graph and twitter meta tags):
    • Enter the description after descMetaTag: string:
    • <descMetaTag:How to use post directives in Galaxie Blog>
    • Terminate the tag with a closing </descMetaTag>

Image XML Post Directives

  • Set the image URL for Facebook (i.e. sets the value for the og:image):
    • Note: if you upload an enclosure when making a post, Facebook and Twitter images will be automatically created for you.
    • Enter the URL after facebookImageUrlMetaData: string:
    • <facebookImageUrlMetaData:/enclosures/facebook/aspectRatio.jpg>
    • Terminate the tag with a closing </facebookImageUrlMetaData>
  • Set the image URL for Twitter (i.e. sets the value for the twitter:image):
    • Note: if you upload an enclosure when making a post, Facebook and Twitter images will be automatically created for you.
    • Enter the URL after twitterImageUrlMetaData: string:
    • <twitterImageUrlMetaData:/enclosures/facebook/aspectRatio.jpg>
    • Terminate the tag with a closing </twitterImageUrlMetaData>

Video XML Post Directives

  • Set the video type. When the proper video type is encountered, the media player will attempt to play the video:
    • The videoType can be: .mp3, .mp4, .ogg .ogv or .webm
    • Specify the video type after videoType: string:
    • <videoType:.mp4>
    • Terminate the tag with a closing </videoType>
  • Set a cover image on top of the video if is not playing (optional):
    • Specify the URL to the cover image after videoPosterImageUrl: string:
    • <videoPosterImageUrl:https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.jpg>
    • Terminate the tag with a closing </videoPosterImageUrl>
  • Set the URL to the small source (576p) of a video (optional):
    • It's possible to have a small, medium and a large video source. The code will determine which video source to play depending upon the end users device type (i.e. desktop or mobile). The large video source should be in 576p format.
    • Specify the URL to the medium sized video after smallVideoSourceUrl: string:
    • <smallVideoSourceUrl:https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-576p.mp4>
    • Terminate the tag with a closing </smallVideoSourceUrl>
  • Set the URL to the medium source (720p) of a video (optional):
    • It's possible to have a small, medium and a large video source. The code will determine which video source to play depending upon the end users device type (i.e. desktop or mobile). The large video source should be in 720p format.
    • Specify the URL to the medium sized video after mediumVideoSourceUrl: string:
    • <mediumVideoSourceUrl:https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-720p.mp4>
    • Terminate the tag with a closing </mediumVideoSourceUrl>
  • Set the URL to the large source (1080p) of a video (optional):
    • It's possible to have a small, medium and a large video source. The code will determine which video source to play depending upon the end users device type (i.e. desktop or mobile). The large video source should be in 1080p format.
    • Specify the URL to the medium sized video after largeVideoSourceUrl: string:
    • <largeVideoSourceUrl:https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-1080p.mp4>
    • Terminate the tag with a closing </largeVideoSourceUrl>
  • Set the URL to the video captions file (optional):
    • Specify the URL to video captions VTT file after the videoCaptionsUrl: string:
    • <videoCaptionsUrl:https://cdn.plyr.io/static/demo/View_From_A_Blue_Moon_Trailer-HD.en.vtt>
    • Terminate the tag with a closing </videoCaptionsUrl>
  • Set the cross origin setting (optional):
    • This is an optional setting that only should be set when the video source is outside of your domain. Set to true only when the video is hosted from another source.
    • Specify the URL to video captions VTT file after the videoCrossOrigin: string:
    • <videoCrossOrigin:true>
    • Terminate the tag with a closing </videoCrossOrigin>
  • Set the video width meta data (optional):
    • This is an optional setting that sets the width in the meta tags. It does not impact the presentation of the video and is only used by Facebook and Twitter.
    • Specify the width in pixels after the videoWidthMetaData: string:
    • <videoWidthMetaData:1920>
    • Terminate the tag with a closing </videoWidthMetaData>
  • Set the video height meta data (optional):
    • This is an optional setting that sets the height in the meta tags. It does not impact the presentation of the video and is only used by Facebook and Twitter.
    • Specify the width in pixels after the videoHeightMetaData: string:
    • <videoHeightMetaData:1080>
    • Terminate the tag with a closing </videoHeightMetaData>

XML Post Directive for YouTube

  • Set the URL to a YouTube Video:
    • Specify the YouTube full URL after the youTubeUrl: string:
    • <youTubeUrl:https://www.youtube.com/watch?v=liJqpsjai9I&feature=youtu.be>
    • Terminate the tag with a closing </youTubeUrl>

XML Post Directive for Vimeo

  • Set the ID to play a video from Vimeo:

XML Post Directives to bypass ColdFusions' Global Script Protection

  • Use a cfinclude:
    • Enter the path to the template that you want to include after the <cfincludeTemplate: string:
    • <cfincludeTemplate:/blog/includes/postContent/parallax/parallaxScript.cfm></cfincludeTemplate>
  • Include a javascript inside of a post
    1. Use the initial attachScript, and place the optional script type, if necessary, after attachScript string within a blog post like so:
    2. <attachScript>
    3. Copy and paste the actual javascript
    4. alert("Hello World");
    5. And terminate the script with </attachScript>:
    6. </attachScript>

This entry was posted on December 14, 2019 at 2:14 PM and has received 112 views.

How to make the perfect social media sharing image - part 6 Validation tools and tips

In this last post in this series, I will provide to links to some social image sharing validator tools and provide a few tips and tricks that I learned along the way.

After creating the proper social media images and fine tuning the social media meta tags that are required, you can validate how each site will display your page using the tools below.

Facebook Sharing Debugger

The Facebook Sharing Debugger will validate your og meta tags and scrape the social media image. It's relatively straightforward to use. Just enter in the URL of the page that you want to validate, and the debugger will scrape your page and show you if any errors were made. When you first enter the URL, it will take several seconds to generate the page, and if this page was not shared before, it will prompt you to fetch new information. Click on the button to fetch new information, and the debugger will list out data along with error information.

The debugger will not immediately generate the Facebook sharing preview as it is crawling your page in the background, wait several minutes and refresh the page, and the image preview should be displayed. If you have errors indicating that you have missing tags, you can ignore these, as long as you have all of the essential tags.

If you don't like the look of the images, you can make some changes, but come back here and regenerate the preview on the pages that you have shared the URL to.

If you're using Galaxie Blog, I have a utility tool in /common/utilities/cfimage.cfm that will allow you to reprocess the images quickly. For non Galaxie Blog users, I have provided instructions below, and I placed the utility script on Git hub.

Twitter Card Validator

The Twitter Card Validator is a bit easier to use, and it responds faster than the Facebook Sharing Debugger. Like Facebook, all that you need is to input your URL. After entering the URL, Twitters tool should immediately display your page preview. However, it is not easy to change the appearance of the preview after it has been made. I'll show you some tricks to re-create the preview.

How to Regenerate a Twitter Preview

Twitter will cache your preview once the page has been shared, or a Twitter Card Preview has been made. However, it can be quite problematic to refresh the cache once made. I learned a few tricks and will show you a bullet proof way to change your preview if you have to make any changes.

Go to the Twitter Open Graph meta tags in your page. Append something unique on the twitter:image tag like so. If you're using ColdFusion you can simply create a UUID. Other languages have the same capabilities. All you need to do is make sure that the URL is unique.

view plain about
1meta name="twitter:image" content="https://gregoryalexander.com/blog/enclosures/twitter/toby.jpg?id=#createUuid()#"

Once you have made the URL to the image unique, Twitter thinks that you have changed the image entirely, and will clear the cache and refresh the preview.

Note: you'll have to get a Facebook and Twitter Developer Account to use these tools.

Creating Social Media Images

I have put a cfimage.cfm template on GitHub for you to generate Social Media Images. I use this to generate social media images for my older posts. The usage is pretty simple. Upload the cfimage file to your server. then drop the original image in a enclosures folder, and create two new folders within the enclosures folder named twitter and facebook. In the socialMediaImagePath variable, put in the full image path for the type of image that you want to create. Go to the URL of your cfimage.cfm template with a browser, and the images will be saved underneath the '/enclosures/facebook' or '/enclosures/twitter' folders.

view plain about
1<!-- This is the only line that you should adjust --->
2<cfset socialMediaImagePath = "D:\home\gregorysblog.org\wwwroot\enclosures\DSC_0518.JPG">
3<!--- Consume the createSocialMediaImages(socialMediaImagePath, socialMediaImageType) function --->    
4<cfset createSocialMediaImages(socialMediaImagePath, 'facebook', '')>
5<cfset createSocialMediaImages(socialMediaImagePath, 'twitter', '')>

Other Social Media Validators

There are other tools for validation for different media platforms, such as Twitters Post Inspector, and Pinterest Rich Pin's Validator that I will cover at a different time.

Happy Coding!

This entry was posted on November 4, 2019 at 3:40 PM and has received 427 views.

How to make the perfect social media sharing image - part 5 Essential Meta Tags


How to make the perfect social media sharing image - part 5 Essential Meta Tags

Sharing your content on social media can have dramatic results at driving more traffic to your site. In my own experience, sharing my own content can drive 50% more traffic to the site. Along with adding the properly sized images, we need to make use of the correct meta tags. I have made several passes at improving the logic that Galaxie Blog uses to auto-generate the tags, and will share my experience with you. If you are using Galaxie Blog, the auto-generation of these tags is done for you.

Each social media site has it's own rules for generating the meta tags. Facebook prefers open graph tags, Twitter can use the open graph tags, but it has a slew of it's own proprietary tags, and Google +, LinkedIn, and Pinterest prefer schema markup tags, which I will not cover here.

Open Graph Tags

The following open graph tags are essential for Facebook

<meta property="og:image" content="URL to the social sharing image.">
<meta property="og:site_name" content="The site name (ie Galaxy Blog). " />
<meta property="og:url" content="The URL to the article" />
<meta property="og:title" content=" Must be 25 characters or less, especially for mobile" />
<meta property="og:description" content="Should be up to two sentences long, but under 30 characters for decent mobile rendering" />

The og:image:height and og:image:width tags are helpful, but not necessary. Facebook will correctly determine the proper image size as long as you stay within the Facebook recommendations.

Essential Twitter Tags

<meta name="twitter:card" content="summary_large_image">Use 'summary_large_image' if you're following along with this article
<meta name="twitter:site" content="@Site or article URL">
<meta name="twitter:title" content="The title of your site or article">
<meta name="twitter:description" content="Description, should be less than 200 characters">
<meta name="twitter:image" content="URL to the social sharing image.">

In the next article, I will go over some useful validation tools and share some tips and tricks with that I found.

This entry was posted on November 2, 2019 at 11:07 PM and has received 250 views.

How to make the perfect social media sharing image - part 3 Get the code...


In this post, I will share how I implemented logic to have Galaxie Blog automatically create social media sharing images for you when uploading an image for a given post.

Background

When a Galaxie Blog owner creates a post using the administrative interface, there is an option to upload an enclosure by clicking a Choose File button at the end of the add entry page. The interface is simple, when the Choose File button is clicked, it opens up a file browser and the user selects the image that they want to be displayed at the top of the post.

In this post, the picture above is an abstract image that is 2200 pixels wide, and 1760 pixels in height. However, the social media images that the code below produces from this image will have different sizes that are optimized for both Facebook and Twitter. Galaxie Blog has always created a responsive image that automatically adjusts itself to fit on any modern device, however, I have now implemented logic that will manipulate the selected image and create both Facebook and Twitter social media images as well. Here is my approach...

Usage

To use this to create and save social media images, all that you need to do is invoke the createSocialMediaImages function below. It takes three arguments, the URL of the image that you want to perform operations on, the social media platform, and optionally, the Social Media Image Type. If the social media type argument is left blank (which is what I use in Galaxie Blog), the function will automatically determine the size and the proper aspect ratio. Here is the production code for Galaxie Blog that is working right now:

view plain about
1<!--- Set the path. --->
2    <cfset socialMediaImagePath = "D:\home\gregoryalexander.com\wwwroot\blog\enclosures\aspectRatio1.jpg">
3    <!--- Automatically generate social media images for Facebook, Twitter, Instagram and LinkedIn. --->
4    <cfset createSocialMediaImages(socialMediaImagePath, 'facebook', '')>
5    <cfset createSocialMediaImages(socialMediaImagePath, 'twitter', '')>
6    <cfset createSocialMediaImages(socialMediaImagePath, 'instagram', '')>
7    <cfset createSocialMediaImages(socialMediaImagePath, 'linkedIn', '')>

Logic Walkthrough

I am assuming that if you're reading this, you're someone with the technical skills that can read this and try it out, so I'll jump right in to briefly cover the core logic of this approach. For the sake of clarity, I will only cover how the logic creates Facebook social media images. Most of the logic for the other platforms are the same, and I'll provide the full code at the end of the article.

Once the blog image is selected by the blog owner, Galaxie Blog will first get the width and height of the uploaded enclosure image that was just uploaded.

view plain about
1<cfimage
2    action = "info"
3    source = "#socialMediaImagePath#"
4    structname="imageInfo">

The logic will then compare the height and width of the original image and determine which type of image will be used. Essentially, are we going to use the largest image type specified by the social media platform, or the minimum depending upon the image that was just uploaded.

view plain about
1<cfcase value="facebook">
2    <!--- Is the original image larger or smaller than Facebook's large image size? If larger, use the larger image dimensions specified by the social media platform. If the original image is smaller, use a smaller sized image. We are going to use similiar logic for every social media platform. --->
3    <cfif imageInfo.width gte facebookSharedImageWidth and imageInfo.height gte facebookSharedImageHeight>
4        <!--- Use the larger social media format. --->
5        <cfset socialMediaImageType = "facebookSharedImage">
6    <cfelse>
7        <cfif imageInfo.width gte facebookLinkRectangleImageWidth and imageInfo.height gte facebookLinkRectangleImageHeight>
8            <cfset socialMediaImageType = "facebookLinkRectangleImage">
9        <cfelse><!---<cfif imageInfo.width gte facebookLinkRectangleImageWidth and imageInfo.height gte facebookLinkRectangleImageHeight>--->
10            <!--- Use the facebookLinkSquareImage --->
11            <cfset socialMediaImageType = "facebookLinkSquareImage">
12        </cfif><!---<cfif imageInfo.width gte facebookLinkRectangleImageWidth and imageInfo.height gte facebookLinkRectangleImageHeight>--->
13    </cfif>
14</cfcase>

First, we will double check the images again to make sure that the uploaded image has a larger size than the social media sharing image that we will create. If the uploaded image is larger, we'll set the width and height to match the larger image type. If the uploaded image is smaller than the largest recommended size, we will use the minimum size recommended by the social media platform, and we may set a pre-crop variable to true if necessary. We'll cover this logic next.

view plain about
1<cfcase value="facebookSharedImage">
2    <!--- Is the original image larger or smaller than the large image size? If larger, use the larger image dimensions specified by the social media platform. If the original image is smaller, use the miniumum size. We are going to use the same logic for every social media type. --->
3    <cfif imageInfo.width gte facebookSharedImageWidth and imageInfo.height gte facebookSharedImageHeight>
4        <!--- Use the larger social media format. --->
5        <cfset thisImageWidth = facebookSharedImageWidth>
6        <cfset thisImageHeight = facebookSharedImageHeight>
7    <cfelse>
8        <!--- Use the rectangular facebook format. --->
9        <cfset thisImageWidth = facebookLinkRectangleImageWidth>
10        <cfset thisImageHeight = facebookLinkRectangleImageHeight>
11        <cfset preCrop = true>
12    </cfif>
13</cfcase>

Resizing a copy of the original uploaded image

Next we'll check to see if the original image is twice as wide as the targetted social media size. If it is, or if the preCrop variable was set in the previous switch statements, we will create a copy of the original image, and then resize the new image. The code below illustrates this. I removed all of the code other than the Facebook code.

view plain about
1<cfif preCrop>
2
3    <!--- Create a new image --->
4    <cfset shareImage = imageNew(socialMediaImagePath)>
5
6    <!--- Handle small images. --->
7    <!--- This logic is only invoked for Facebook rectangle links. --->
8    <cfif socialMediaImageType eq 'facebookLinkRectangleImage'>
9
10        <!--- Resize the new image. For portrait images, we are going to resize the image to 550 pixels wide. --->
11        <cfset imageResize(shareImage, 550, '')>
12        <!--- We know the width of the new image that was just created (550), now get it's height --->
13        <cfset shareImageWidth = imageGetHeight(shareImage)>
14        <!--- Crop the resized image from the center (centerCrop(path/image, originalWidth, originalHeight, newWidth, newHeight). We don't need to determine an aspect ratio. It is a square. --->
15        <cfset shareImage = centerCrop(shareImage, 550, shareImageWidth, thisImageWidth, thisImageHeight)>
16
17    </cfif><!---<cfif (socialMediaImageType eq 'facebookLinkRectangleImage'>--->
18</cfif>

Maintaining the aspect ratio using our nifty ColdFusion ratio calculator function

One of the most critical requirements or this is having the ability to resize images while maintaining the targeted aspect ratio. I could not find a ColdFusion function that did this, so I had to built my own. If you play around with manipulating images and aspect ratios, this type of function should belong in your own toolbox.

Our ratioCalculator function below takes 3 arguments. The aspectRatioWidth and aspectRatioHeight arguments should match the recommended width and height of our targetted social media image that are indicated in the prior post. For the large Facebook Shared Image, the ratio aspect is 1200 pixels wide, and 630 pixels in height. We'll go ahead and plug these values in for the first two arguments as this is the aspect ratio that we want to keep, no matter what size we eventually resize the image to. The third argument is the newWidth argument. Here, the newWidth argument will either be: the original width of the uploaded image: or, the new width when we resized the image in the step above when the size of the uploaded image was twice the width of the recommended Facebook image size.

The ratio calculator function will take these three values, and return the height that is needed to maintain the original aspect ratio. To get the new height of the image, all that we need to specify is the recommended width and height, provided by the social media platform, and the new width that we want to resize an image to be. The new width argument can be smaller, or larger, than the aspect ratio size. No matter what you plug in for the new width, the aspect ratio will be maintained.

view plain about
1<cffunction name="ratioCalculator" access="public" output="true" returnType="numeric" hint="This is used to determine the new dimensions needed to fit a certain width while maintaining the specified aspect ratio. I am using this to determine how to resize an image to meet the aspect ratio used by varius social media sites.">
2    <cfargument name="aspectRatioWidth" required="yes" hint="Specify the original width of the image.">
3    <cfargument name="aspectRatioHeight" required="yes" hint="Specify the original height of the image.">
4    <cfargument name="newWidth" required="yes" hint="Specify the desired width of the new image.">
5
6    <cfset newHeight = (arguments.aspectRatioHeight / arguments.aspectRatioWidth) * arguments.newWidth>
7
8    <cfreturn newHeight>
9</cffunction>

Cropping the images

The code has two cropping functions, centerCrop, and horizontalCrop. The centerCrop function is used when we have a landscape image, and the horizontalCrop function is used when using a portrait image.

The centerCrop function takes five arguments, we need to specify the full path of the image, or the variable of the image if we are creating a new image using the newImage ColdFusion function. The original width and original height arguments using the social media recommended size. Here, we are using the large Facebook size of 1200 for the originalWidth, and 630 for the originalHeight. The fourth argument, width, is either the width of the uploaded image, or the width of the newly resized image, and finally, new height, which is provided by the ratioCalculator function that we just covered above. This function will crop the image from the center.

view plain about
1<cffunction name="centerCrop" access="public" output="true" returnType="string" hint="Used to crop an image with a desired size that is smaller both horizontally and vertically than the original image. This will crop the image from the center.">
2        <cfargument name="imagePath" required="yes" hint="Provide either the full original path of the image, or the actual ColdFusion image using the newImage function.">
3        <cfargument name="originalWidth" required="yes" hint="Provide the original width of the image.">
4        <cfargument name="originalHeight" required="yes" hint="Provide the original width of the image.">
5        <cfargument name="newWidth" required="yes" hint="Provide the desired width of the cropped image.">
6        <cfargument name="newHeight" required="yes" hint="Provide the desired height of the new cropped image.">
7        <!--- Local debugging carriage. If something goes awry, set this to true. --->
8        <cfset debug = true>
9        
10        <!--- This algorithm was found at https://www.raymondcamden.com/2010/02/03/Cropping-to-the-center-of-an-image --->
11        <cfset originalImage = "#arguments.imagePath#">
12        <!--- Make a copy of the original image. --->
13        <cfset croppedImage = imageNew(originalImage)>
14        <!--- Get the coordinates. We will subtract the orinal width minus the new width to grab the center of the new image. --->
15        <cfset xCoordinate = (originalWidth - newWidth) / 2>
16        <cfset yCoordinate = (originalHeight - newHeight) / 2>
17            
18        <cfif debug>
19            <cfoutput>
20                originalWidth: #originalWidth#<br/>
21                originalHeight: #originalHeight#<br/>
22                newWidth: #newWidth#<br/>
23                newHeight: #newHeight#<br/>
24                xCoordinate #xCoordinate#<br/>
25                yCoordinate" #yCoordinate#<br/>
26            </cfoutput>
27        </cfif>
28            
29        <!--- Crop the image. --->
30        <cfset imageCrop(croppedImage, xCoordinate, yCoordinate, newWidth, newHeight)>
31            
32        <!--- And return it. --->
33        <cfreturn croppedImage>
34    </cffunction>

The horizontalCrop, used when we are uploading a portrait image, leaves the width intact, but crops the top and the bottom of the picture equally. This function takes three arguments, the imagePath (or the variable name of the new image when we use the imageNew ColdFusion function), the original height of the uploaded image, and the new height. I am using our ratioCalculator function to provide the new height again while maintaining the original aspect ratio recommended by the social media platform. Again, this example uses the large Facebook size of 1200 for the originalWidth, and 630 for the originalHeight.

view plain about
1<cffunction name="horizontalCrop" access="public" output="true" returnType="string" hint="Used to crop a horizontal image that has a horizontally size that is greater than the desired size of the new image. This will crop the image from the horizontal center.">
2        <cfargument name="imagePath" required="yes" hint="Provide the full original path of the image.">
3        <cfargument name="originalHeight" required="yes" hint="Provide the original width of the image.">
4        <cfargument name="newHeight" required="yes" hint="Provide the desired height of the new cropped image.">
5        <!--- Local debugging carriage. If something goes awry, set this to true. --->
6        <cfset debug = true>
7        
8        <!--- This algorithm was found at https://www.raymondcamden.com/2010/02/03/Cropping-to-the-center-of-an-image --->
9        <cfset originalImage = "#arguments.imagePath#">
10        <!--- Make a copy of the original image. --->
11        <cfset croppedImage = imageNew(originalImage)>
12        <!--- Get the coordinates. The x coordinate starts at 0. The image only needs to be cropped vertically. --->
13        <cfset xCoordinate = 0>
14        <cfset yCoordinate = (originalHeight - newHeight) / 2>
15            
16        <cfif debug>
17            <cfoutput>
18                originalHeight: #originalHeight#<br/>
19                newHeight: #newHeight#<br/>
20                xCoordinate #xCoordinate#<br/>
21                yCoordinate" #yCoordinate#<br/>
22            </cfoutput>
23        </cfif>
24            
25        <!--- Crop the image. --->
26        <cfset imageCrop(croppedImage, xCoordinate, yCoordinate, newWidth, newHeight)>
27            
28        <!--- And return it. --->
29        <cfreturn croppedImage>
30            
31    </cffunction>

This is a rather long and complex post. In my next post, I'll provide some concise examples of social media images that this function creates.

Get the code

The code is published as a git hub repository. This component will also become a part of Galaxie Blog in the next release.

Further Reading

Some of the logic in the center crop function was taken from Raymond Camden's article at https://www.raymondcamden.com/2010/02/03/Cropping-to-the-center-of-an-image

This entry was posted on November 1, 2019 at 1:07 AM and has received 276 views.

How to make the perfect social media sharing image - part 2 Getting the Size Right

There is a lot of information about this on the web- but unfortunately, most of it is wrong or outdated. And this is not necessarily due to the author's mistake. The social media platforms are always fine tuning their image formats and the information changes. To make matters worse, there is conflicting information even when going straight to the source, ie Facebook or Twitter.

For example, here twitter recommends using a 2x1 image ratio1 for their large summary cards, however, twitter has new documentation on it's business page mentioning the new 1.91:1 aspect ratio that was updated this August 2. Faceook is a bit better, but there is an overwhelming amount of information out there, and much of it is confusing. I had to learn the proper aspect ratios by digging into a lot of posts, and through trial and error. I have dug into at least a dozen posts for each image type and this is what I came up with and what proved to work for me best.

The following information should be correct as of October 28 2019. I will periodically try to update this list.

  • Twitter

    • Twitter Summary Card with a large image (1.91:1 aspect ratio):

      • Recommended width: 1200 pixels
      • Recommended height: 628

      • Minimum width: 518
      • Minimum height: 226
  • Facebook
    Facebook has a few more options. There is a large image type, but you can also choose from two different smaller image types. The smaller types allow the text to be floated to the right of the image whereas the larger type puts the text at the bottom underneath a larger image. The aspect ratio for the large image size is just a hair bigger than Twitter's Summary Card.

    • Facebook Shared Image (extremely close to the 1.91:1 twitter format, Facebook has a 1.91 aspect ratio):
      • Recommended width: 1200
      • Recommended height: 630

    • Facebook Link Image - Rectangular
      • Minimum width: 484
      • Minimum height: 252

    • Facebook Link Image - Square
      • Minimum width: 116
      • Minimum height: 116
  • Instagram

    • Recommended width: 1080 (1x1 aspect ratio)
    • Recommended height: 1080

    • Minimum width: 600
    • Minimum height: 315
  • Linked In
    LinkedIn images are very narrow and wide.

    • Recommended width: 1128
    • Recommended height: 376

    • Minimum width: 502
    • Minimum height: 282

If this sounds a little confusing, read on to the next post. In the next post, I will show the actual dimensions of each image type, and provide information how to use ColdFusion to manipulate images to obtain the desired size while keeping the proper aspect ratio.


1A 2x1 aspect ratio is recommended on this particular twitter page "Images for this Card support an aspect ratio of 2:1 with minimum dimensions of 300x157 or maximum of 4096x4096 pixels"
2
Yet, this twitter page suggests the new 1.91:1 aspect ratio: "Image size: 800 x 418 pixels for 1.91:1 aspect ratio, 800 x 800 pixels for 1:1 aspect ratio"

This entry was posted on October 28, 2019 at 11:21 PM and has received 292 views.

How to make the perfect social media sharing image - part 1 Background


Have you wondered how to get a perfect image from your blog when you share your post on social media? I have... and after spending several weeks on this; I think that I have managed to figure it out...

Over the course of the last few months, I have spent quite a bit of time trying to figure out how to effectively share my content on social media sites. I had thought to simply share the image at the top of each post, but I didn't get the size of the image right. The proper image size was different for each social media platform. Finding the proper sizes between the social media platforms was daunting. The information available on the net is often contradictory, and constantly subject to change. Figuring out the proper approach necessitates aiming at a constantly moving target. What worked several months ago might not work the same now.

After failing at my initial attempt; I reverted the Galaxie Blog code and used the same default social media image that tended to work for every post. While I was sick of looking at the same mountain logo on every social media post (I assume along with my three regular readers), I had more pressing tasks to deal with. There have been a lot of other features that I wanted to put into this blog first, and wanted to wait until I could take a few weeks to devote to learn by trial and error to get this social media image sharing thing right.

There are also other considerations other than just manipulating the image. The social media platforms need to have certain meta tags. After spending the last couple of weeks I found a good approach to solve this. In the next several posts, I will share my journey with you and show you my Galaxie blog implementation. Along the way, I'll provide some ColdFusion scripts for you to resize your own images for social media sharing on your own. Additionally, I hope to provide you some helpful tips.

This entry was posted on October 28, 2019 at 11:29 AM and has received 310 views.




Footer Logo

Your input and contributions are welcomed!

If you have an idea, BlogCfc based code, or a theme that you have built using this site that you want to share, please contribute by making a post here or share it by contacting us! This community can only thrive if we continue to work together.

Images and Photography:

Gregory Alexander either owns the copyright, or has the rights to use, all images and photographs on the site. If an image is not part of the "Galaxie Blog" open sourced distribution package, and instead is part of a personal blog post or a comment, please contact us and the author of the post or comment to obtain permission if you would like to use a personal image or photograph found on this site.

Credits:

Portions of Galaxie Blog are powered on the server side by BlogCfc, an open source blog developed by Raymond Camden. Revitalizing BlogCfc was a part of my orginal inspiration that prompted me to design this site. Some of the major open source contributers to BlogCfc include:

  1. Peter Farrell: the author of 'Lyla Captcha' that is used on this blog.
  2. Pete Freitag: the author of the 'ColdFish' code formatter that is also used on this blog.

Version:

Galaxie Blog Version 1.50 November 22 2019