Enable Instant Articles for Facebook on your Episerver site
Instant Articles is a publishing format that enables publishers to distribute articles through Facebook's mobile app. It´s optimized for fast mobile performance with rich storytelling capabilities, branded design and customized visual display. Read more about Instant Articles.
![](https://github.com/BVNetwork/InstantArticles/blob/master/doc/img/facebook instant article .jpg)
- This tool adds support for Facebook Instant Articles by creating a RSS feed of your articles that Facebook consumes
- Supporting Episerver CMS and Episerver Commerce
- A best effort is made to generate valid Instant Article markup from the article source
The installation is done through Visual Studio by installing the nuget created from this project. Let your article page type implement IInstantArticlePage and implement the required method and property.
Implementation examples:
public IInstantArticle CreateInstantArticle(InstantArticleRssPage rssPage)
{
var instantArticle = this.CreateInstantArticleBase();
instantArticle.Body = MainBody;
instantArticle.Authors = GetInstantArticleAuthors();
instantArticle.ExcludeFromFacebook = ExcludeFromFacebook;
instantArticle.Image = Image; //Main image of the article
instantArticle.ImageCaption = ImageCaption; //Caption text for the main image
instantArticle.Kicker = Kicker; //Kicker text
instantArticle.Subtitle = MetaDescription;
instantArticle.Title = PageName;
instantArticle.ArticleStyle = rssPage.DefaultArticleStyle;
return instantArticle;
}
private IList<IInstantArticleAuthor> GetInstantArticleAuthors()
{
//Using Episerver Relations to retrive authors for this article https://github.com/BVNetwork/Relations
var authorsPageData = EPiCode.Relations.Helpers.PageHelper.GetPagesRelated(this.ContentLink.ToPageReference(), "ArticleWriter").Cast<IInstantArticleAuthorContent>();
var instantArticleAuthors = new List<IInstantArticleAuthor>();
foreach (var author in authorsPageData)
{
instantArticleAuthors.Add(author.CreateInstantArticleAuthor());
}
return instantArticleAuthors;
}
For images to be shown correctly inside the article (MainBody) you have to take control over the markup normaly generated by TinyMCE. This leaves you with two options:
-
- Create your own ImageModel class, inherit from ImageData and implement IInstantArticleImageFile
-
- Create your own ImageBlockModel by inheriting from from BlockData (or any derived class) and implement IInstantArticleImageBlock
The first option is prefert for sites that not requires globalisation. Due to the fact that ImageData is not localizable you have to go for the second solution if you have content in more then one language.
#####Example using the ImageModel approach#####
public class ImageFile : ImageData, IInstantArticleImageFile
{
[Display(
Name = "Image caption",
Description = "Descriptive text for your image. May also include attribution to the originator or creator of this image.",
Order = 10)]
[CultureSpecific]
public virtual string ImageCaption { get; set; }
[Display(
Name = "Alt text",
Description = "Sets Alt text of the image.",
Order = 20)]
[CultureSpecific]
public virtual string AltText { get; set; }
public IInstantArticleImage CreateInstantArticleImage()
{
return new InstantArticleImage()
{
Image = this.ContentLink,
ImageCaption = ImageCaption
};
}
#####Example using ImageBlockModel approach#####
public class ImageBlock : BlockData, IInstantArticleImageBlock
{
[Display(
Name = "Image",
Description = "Reference to the image",
Order = 10)]
[UIHint(UIHint.Image)]
public virtual ContentReference Image { get; set; }
[Display(
Name = "Image text",
Description = "Descriptive text for your image. May also include attribution to the originator or creator of this image.",
Order = 20)]
[CultureSpecific]
public virtual string ImageCaption { get; set; }
public IInstantArticleImage CreateInstantArticleImage()
{
return new InstantArticleImage()
{
Image = Image,
ImageCaption = ImageCaption
};
}
}
###Add a new property to your start page###
[Display(GroupName = Global.GroupNames.SiteSettings, Name = "Instant Article RSS page", Description = "A reference to the page Instant Article RSS Page")]
public virtual PageReference InstantArticleRssPage { get; set; }
###Create an implementation of IInstantArticleService and set it up with IOC ### #####Example using Episerver Find#####
[ServiceConfiguration(ServiceType = typeof(IInstantArticleService))]
public class InstantArticleService : IInstantArticleService
{
private static readonly ILogger logger = LogManager.GetLogger();
private IContentRepository _contentRepository;
public IEnumerable<IInstantArticlePage> GetAllInstantArticlePages()
{
var articles = SearchClient.Instance.Search<PageData>()
.Filter(x => x.MatchTypeHierarchy(typeof(IInstantArticlePage)))
.Take(1000)
.FilterForVisitor()
.Filter(x => ((IInstantArticlePage)x).ExcludeFromFacebook.Match(false))
.OrderByDescending(x => x.StartPublish)
.GetContentResult();
return articles.Cast<IInstantArticlePage>();
}
public InstantArticleRssPage GetInstantArticleRssPage()
{
var InstantArticleRssPageRef = _contentRepository.Get<StartPage>(ContentReference.StartPage).InstantArticleRssPage;
try
{
return _contentRepository.Get<InstantArticleRssPage>(InstantArticleRssPageRef);
}
catch (Exception exception)
{
logger.Error("Please specify Instant Article RSS page on start page under Site settins", exception);
throw;
}
}
public InstantArticleService(IContentRepository contentRepository)
{
_contentRepository = contentRepository;
}
}
#####Example NOT using Episerver Find##### Swap the method GetAllInstantArticlePages with this implementation:
public IEnumerable<IInstantArticlePage> GetAllInstantArticlePages()
{
var articles = new List<PageData>();
FindAllInstantArticles(articles, ContentReference.StartPage);
return articles.Cast<IInstantArticlePage>();
}
private void FindAllInstantArticles(List<PageData> list, ContentReference parentPage)
{
var loader = ServiceLocator.Current.GetInstance<IContentLoader>();
var children = loader.GetChildren<PageData>(parentPage);
children.ForEach(pg =>
{
if (pg is IInstantArticlePage)
{
list.Add(pg);
}
FindAllInstantArticles(list, pg.ContentLink);
});
}
}
Create a RSS page and set the default article style in Episerver edit view. (You define your custom Instant Article style on your Facebook page).
Your are now ready to let Facebook start consuming your RSS feed. Follow the starterguide here: https://developers.facebook.com/docs/instant-articles/quickstart
##Known problems and limitations## If the article contains internal links (within the Episerver site) it could cause Facebook to generate a warning. This warning is safe to ignore, Facebook are accepting realative links just fine. If your article contains span-element inside p-element , the span-element will be removed.