--- layout: handbook-page-toc title: "Blog Handbook" --- The [GitLab blog](/blog) is managed by [@rebecca](https://gitlab.com/rebecca) the [Managing Editor](/job-families/marketing/editor/). ## Communication - [Public issue board](https://gitlab.com/gitlab-com/www-gitlab-com/boards/804552?&label_name[]=blog%20post); to propose a blog post, create a new issue and label it `blog post`. - Chat channels; use `#content` for questions, `#content-updates` for updates on most recently published articles. ## On this page {:.no_toc .hidden-md .hidden-lg} - TOC {:toc .hidden-md .hidden-lg} ## Other related pages - [Process for making an announcement](/handbook/marketing/corporate-marketing/#requests-for-announcements) - [GitLab Unfiltered blog](/handbook/marketing/blog/unfiltered/) - [Editorial team page (including blog style guide)](/handbook/marketing/corporate-marketing/content/editorial-team/) - [Brand personality](/handbook/marketing/corporate-marketing/#brand-personality) and [tone of voice guidelines](/handbook/marketing/corporate-marketing/#tone-of-voice) - [Content Hack Day](/handbook/marketing/corporate-marketing/content/content-hack-day/) - [Monthly release post](/handbook/marketing/blog/release-posts/) ## Goal: Grow our audience, engage readers, and convert readers into subscribers The GitLab blog exists for our audience and we serve our audience first. Without an audience, blog content cannot support our objectives. Every blog post published on the GitLab blog should be crafted with our audience needs and wants in mind. The GitLab blog is not self-serving; if content is purely promotional and adds no value to our readership, it will not be published. **We measure success by tracking the following metrics:** 1. Engagement: # of page views 1. Reach: # of new visitors 1. Conversion: # of subscribers both net new and total ## Objectives 1. Build credibility and authority. 1. Increase awareness of GitLab the company, product, and community. 1. Increase organic search rankings and traffic. 1. Contribute to lead generation and revenue. ## Scope **Mission statement:** Create, curate, and elevate stories that increase awareness of the benefits of a single application for the entire DevOps lifecycle, as well as awareness of GitLab as a pioneer in all-remote work. Please see [Attributes of a successful blog post](/handbook/marketing/blog/#attributes-of-a-successful-blog-post) below for examples of stories that perform well on our blog. The blog is not the permanent place for tutorials, which should live in the docs and should be linked to when relevant. ### Ideal content mix #### Definitions 1. **Technical:** Articles which dive deep into a technical topic and provide technical details on how to use, implement, or solve something. Technical articles often include code snippets or screen shots, and provide tangible results or actions for the reader. - Examples: - [What tracking down the missing TCP Keepalives taught me about Docker, Golang, and GitLab](/blog/2019/11/15/tracking-down-missing-tcp-keepalives/) - [The Consul outage that never happened](/blog/2019/11/08/the-consul-outage-that-never-happened/) - [Improve your productivity by tracking your time and measuring your E-factor](/blog/2019/11/26/e-factor-productivity/) 1. **Features:** Articles which provide scope, depth, and interpretation of trends, events, topics, or people. Includes articles covering customer stories, trends and/or data analysis, and journalistic reporting on a topic, event, or person. - Examples: - [The cloud adoption roadmap](/blog/2019/12/05/cloud-adoption-roadmap/) - [A brief guide to multicloud security](/blog/2019/11/21/multi-cloud-security/) - [The DevOps tool landsacpe](/blog/2019/11/01/devops-tool-landscape/) 1. **Product:** Articles that cover GitLab's product evolution, features, and capabilities. Includes release posts, integrations, feedback solicitations, and use case articles centered around how to use GitLab to do something. - Examples: - [Why GitLab CI/CD?](/blog/2019/04/02/why-gitlab-ci-cd/) - [How we are interating on Group Single Sign On for GitLab.com](/blog/2019/01/17/iterating-on-sso/) - [3 Major improvements coming to GitLab Epics](/blog/2020/01/21/epics-three-features-accelerate-your-workflow/) 1. **Remote work:** Articles that cover all-remote work. Includes articles about work/life balance, tricks and tips, building an all-remote company, etc. - Examples: - [The GitLab handbook by numbers](/blog/2019/04/24/the-gitlab-handbook-by-numbers/) - [Mastering the all-remote environment: My top 5 challenges and solutions](/blog/2019/12/30/mastering-the-all-remote-environment/) - [6 Ways to improve communicationin your company](/blog/2019/12/23/six-key-practices-that-improve-communication/) 1. **Corporate news:** Articles covering GitLab news and announcements such as: - Changes to GitLab policies, product, and services. Examples: - [Update on free software and telemetry](/blog/2019/10/10/update-free-software-and-telemetry/) - [Why we're ending support for MySQL](/blog/2019/06/27/removing-mysql-support/) - GitLab company news. Example: - [Announcing $268 million in Series E funding](/blog/2019/09/17/gitlab-series-e-funding/) - Announcements and updates about internal programs. Example: - [Inside the GitLab public bug bounty program](/blog/2019/04/29/inside-the-gitlab-public-bug-bounty-program/) - Joining a new program or foundation. Examples: - [GitLab leads the industry forward with the CD foundation](/blog/2019/03/12/gitlab-joins-cd-foundation/) - [GitLab is now a member of the OWASP Foundation](/blog/2020/01/21/gitlab-is-now-a-member-of-the-owasp-foundation/) - Awards. Example: - [GitLab achieves AWS DevOps Competency certification](/blog/2018/11/28/gitlab-achieves-aws-devops-competency-certification/) - Analyst reports. Example: - [GitLab named a 'Visionary' in 2019 Gartner Enterprise Agile Planning Tool Magic Quadrant](/blog/2019/05/22/gitlab-identified-by-gartner-as-eapt-visionary/) - Partner announcements. Examples: - [GitLab on AWS Marketplace](/blog/2019/06/11/gitlab-on-aws-marketplace/) - [GitLab + Salesforce](/blog/2019/05/29/sfdx-promo-trailhead-blog/) - [ZEIT launches Now for GitLab](/blog/2019/04/01/zeit-launches-now-for-gitlab/) - Offers. Example: - [Extending free use of CI/CD for GitHub on GitLab.com](/blog/2019/03/21/six-more-months-ci-cd-github/) ## Publishing process If you'd like to write about something for the GitLab blog, please follow the instructions below to pitch your idea to the Editorial team. This process is intended to ensure the Editorial team is spending the bulk of their time working on posts that get results and align with the goals for the blog. If you prefer, you can submit a complete blog post to the [GitLab Unfiltered blog](/handbook/marketing/blog/unfiltered/) without pitching first. The [Unfiltered blog is monitored weekly for posts to feature](/handbook/marketing/corporate-marketing/content/editorial-team/#featuring-unfiltered-posts) on the main blog. Unfiltered posts are not shared on GitLab's official social media handles. **Why do we use a pitching process?** Many people throughout GitLab the company and community contribute to the blog. Our pitching process ensures we can prioritize submissions so we don't overwhelm our audience with too much content at once, and to help our contributors craft their ideas in a way that will get views. After reviewing years of data, we know what type of content is likely to get views and what is unlikely to resonate. We want to help every contributor maximize the impact of their contribution. Data shows that more blog posts does not equal more views. In fact, too much content can have a negative impact on our traffic. The pitching process allows us to review each article and schedule it at the most appropriate time. We've found that publishing ~3 articles per week is the most effective publishing cadence for the GitLab blog. ### How to pitch a blog post Open an issue in the [gitlab.com/gitlab-com/www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com/issues) project, using the `Blog post` template. Include a short summary of your proposed blog post where indicated, and add the `Blog::Pitch` label to ensure your pitch is triaged. If you hope to publish on a specific date or within a specific timeframe, please allow at least three weeks' lead time from the date you open your issue and ping `@rebecca` immediately, as the [Editorial calendar](#blog-calendar) fills up quickly and we cannot guarantee there will be a slot for your post without adequate notice. Please give a rationale for your proposed publish date in the issue description so the team can prioritize accordingly. If you do not intend to write the post yourself but are just suggesting an idea you think would be worth pursuing, please make this clear in your issue description. Note: If you're planning to write a tutorial post describing how to do something with GitLab, please ensure that the relevant [documentation](https://docs.gitlab.com/) exists _first_ before you write a blog post about it. A blog post should not replace documentation, but should add more information, context, and color around a technical subject, linking back to the documentation for full instructions. {: .alert .alert-info .note} ### Triage of pitches The Editorial team will review issues with the label `Blog::Pitch` every Monday, and a team member will respond on your issue to let you know whether to move forward with your draft. If your pitch isn't accepted, no problem! The Editorial team will suggest that you submit your post to the [GitLab Unfiltered blog](/handbook/marketing/blog/unfiltered/) instead. The [Unfiltered blog is monitored weekly for posts to feature](/handbook/marketing/corporate-marketing/content/editorial-team/#featuring-unfiltered-posts) on the main blog. ### How to get your blog post pitch accepted The team will be assessing pitches against the following criteria: 1. The post idea aligns with the [blog objectives](/handbook/marketing/blog/#objectives) and [scope](/handbook/marketing/blog/#scope); and/or 1. The idea shows potential to become [a high-performing post](/handbook/marketing/blog/#attributes-of-a-successful-blog-post) To give your idea the best chance of being accepted, be sure to demonstrate how your pitch meets the criteria above. It may also help to think about the following: 1. Who is your post for? (i.e. Who is the intended audience?) 1. What will readers gain from reading your post? What will they learn? 1. Are there tangible examples/outcomes you can share to illustrate your points? Issues/MRs/epics you can link to? 1. What makes this post different to other blog posts on this topic (on the GitLab blog or elsewhere)? 1. What makes you the best person to write about this topic? What unique experience or insight do you bring to it? Showing how your proposed blog posts meets the criteria and that you've given thought to the considerations above will give your pitch the best chance of being accepted. ### Examples of strong blog post pitches Below are links to blog post proposals that demonstrate the value the post will offer to the reader: - [Speed up your Sketch design specs using GitLab pages](https://gitlab.com/gitlab-com/content-hack-day/issues/103) - [How we turned a 40 person synchronous meeting into a podcast](https://gitlab.com/gitlab-com/content-hack-day/issues/181) - [Fixing Git mistakes](https://gitlab.com/gitlab-com/content-hack-day/issues/146) - [How to avoid broken master with Pipelines for merged results and Merge Train](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4786) - [Git performance on NFS](https://gitlab.com/gitlab-com/www-gitlab-com/issues/4653) ### If your pitch is accepted 1. Feel free to start your draft using this [blog post template](https://docs.google.com/document/d/1TavHlYbHQ8U1C82TEzcYaLS9l0sm89jEcBNQ0gBgkcw/edit) which has all the relevant information already embedded. Then see the [formatting guidelines](#formatting-guidelines) for help with creating and formatting your blog post MR. 1. Use the `Blog post` merge request template for your MR and ensure it is set to close the associated issue automatically. 1. Assign the issue and associated merge request to yourself and apply the appropriate labels based on what stage of creation you are on. Once it's ready for editorial review, assign both to @rebecca. She will assign a member of the Editorial team to review the post. Note for the Content team: If your blog post is already scheduled and appears on the [blog calendar](/handbook/marketing/blog/#blog-calendar) please submit your MR and associated issue directly to @vsilverthorne or @skassabian for review. {: .alert .alert-info .note} Blog post ideas and proposals for [Content Hack Day](/handbook/marketing/corporate-marketing/content/content-hack-day/) should be created in the [Content Hack Day project](https://gitlab.com/gitlab-com/content-hack-day). We keep these issues in a separate project because not all ideas and proposals that come from Hack Day will be worked on. ## Time-sensitive posts: Official announcements, company updates, breaking changes, and news Before you open an issue for making an official announcement or sharing a company update or other news on the blog, please see the [PR handbook](/handbook/marketing/corporate-marketing/#requests-for-announcements) regarding announcements. In some cases we may communicate the announcement via channels other than the blog. If the Corporate Communications team decides that we will go ahead with a blog post, please follow [the process outlined below](/handbook/marketing/blog/#process-for-time-sensitive-posts). ### Posting to solicit feedback If you want to solicit feedback on an issue (e.g. gathering community input on a proposal) or encourage people to take part in a survey, it is best to promote the issue or survey itself rather than publishing a blog post which then points people to another place to give their feedback. This has a few advantages: 1. Your issue/survey remains the single source of truth for communication on the subject, rather than spreading communication across a blog post and another page. 1. There is one fewer step/link to click on for community members to share their feedback. 1. Keeping things in an issue/survey reinforces that a final decision has not yet been made, whereas a blog post can give the impression of being a formal announcement rather than a proposal. This can have a negative impact on brand sentiment. We can spread the word about gathering feedback on something in the same way that we would promote a blog post: 1. You can [request promotion of your item on GitLab's social channels](/handbook/marketing/corporate-marketing/social-marketing/#requesting-social-posts-). 1. You can request that your item be included in an upcoming newsletter by leaving a comment on the appropriate [newsletter issue](https://gitlab.com/gitlab-com/marketing/digital-marketing-programs/issues?label_name%5B%5D=Newsletter). 1. Ask in #marketing on Slack if you would like to promote in some other way. ### Joint announcements Joint announcements with partners or other third parties should first be [proposed to the Corporate Communications team](/handbook/marketing/corporate-marketing/#requests-for-announcements) ahead of writing to maximize impact and ensure alignment across teams. They will decide whether we issue a press release, blog post, or communicate via other channels. If they decide to move forward with a blog post, please follow the instructions to [pitch the blog post idea](/handbook/marketing/blog/#how-to-pitch-a-blog-post) to the Editorial team. If we are doing a joint announcement with another company, the announcement post should appear on one party's site, to maximize impact. If both parties wish to publish a blog post about an announcement, the posts should be original and each take a unique angle, offering something new and valuable to the reader. In some cases this may mean a post takes more time to be researched, written, and reviewed, which may necessitate publishing shortly after the official announcement, if planning further ahead is not possible. Posts tend to get more traffic with this approach, rather than publishing and promoting duplicate posts on two blogs, or rushing to get a straightforward announcement out. ### Process for time-sensitive posts If you have followed the directions in the [PR handbook](/handbook/marketing/corporate-marketing/#requests-for-announcements) and the Corporate Communications team has decided that a blog post is the best way to communicate your announcement, please follow the process below. 1. Start by opening an issue in the [gitlab.com/gitlab-com/www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com/issues) project, using the `Blog post` template and applying the `priority` label. **Even if you do not have a draft or a confirmed publish date, it's important to open the issue as far in advance as possible and ping @rebecca so she knows it is coming and can prioritize accordingly.** 1. The issue title should reflect the date on which you expect to publish. 1. The issue due date should be a _minimum_ of two working days before the publish date. 1. If other due dates apply (for example, design assets are required) make sure the entire timeline and all the people responsible are captured in the issue description. 1. In most cases, we expect that you or one of your team will write the post and create the merge request for it, with all images and other formatting included. Feel free to start your draft using this [blog post template](https://docs.google.com/document/d/1TavHlYbHQ8U1C82TEzcYaLS9l0sm89jEcBNQ0gBgkcw/edit) which has all the relevant information already embedded. Then see the [formatting guidelines](#formatting-guidelines) for help with creating and formatting your blog post MR. 1. **If you need assistance with drafting the post or creating the MR, please make this clear in your issue and we will confirm if this is possible within your timeframe.** 1. Use the `Blog post` merge request template for your MR and ensure it is set to close the associated issue automatically. 1. Be sure to check the review app for your blog post or preview it locally to ensure images, headlines, etc. are formatted correctly before handing over. 1. When your MR is ready for review, please assign it and the corresponding issue to @rebecca (or @vsilverthorne or @skassabian if Rebecca is OOO) a _minimum_ of two working days ahead of when you expect to publish. **Please submit your MR earlier if you can**. 1. When you've assigned your MR and issue to a reviewer, please change the due date on the issue to reflect the publishing date. 1. Your reviewer may leave comments for you to address, in which case they will assign the MR back to you. When you have resolved all outstanding discussions, assign the MR back to the reviewer for final review and merging. #### Who to assign your MR to – urgent posts Please assign first to @rebecca. If she is OOO, assign to @vsilverthorne/@skassabian. If no one is available and you cannot wait until they return, please assign to a member of the Technical Writing team. Where possible, select the technical writer who is [listed for the most relevant stage group](/handbook/product/categories/#devops-stages). If you need immediate assistance/review, find a technical writer who is online on Slack to request this directly. Regardless, be sure to specify any time constraints around getting the content reviewed and posted. Continuous delivery mindset: With time-sensitive posts, don't wait to publish a post if you have enough information to go live. It's OK to publish a headline and paragraph to get the news out in a timely matter and add more details later (e.g. add more graphics, charts, etc.). We don't want to miss out on a news cycle because we're waiting for an image or supplementary information. {: .alert .alert-info} ### Error budgets for time-sensitive posts Inspired by [error budgets used by Engineering](/handbook/engineering/#error-budgets). Applied to the blog, error budgets incentivize forward planning and early communication of time-sensitive blog posts. This helps the Editorial team to minimize time spent on unplanned work, shuffling of the publishing schedule, or work that is subsequently wasted or does not serve our [mission and vision](/handbook/marketing/corporate-marketing/content/#mission--vision), or the needs of our audience. Each functional group is responsible for not exceeding an allowed budget of 15 points per quarter. The number of points given will depend on the severity of the impact to the team's workflow: - S1: 15 points - Less than 2 working days' notice for a time-sensitive post (except in cases of responding to an industry or company event/news for which there was no prior warning). - S2: 10 points - Failure to submit complete, formatted MR a _minimum_ of 2 working days ahead of publish date. - S3: 5 points - MR submitted ahead of time, but without all required formatting, links, and images included (unless otherwise agreed). Where error budget points are incurred, a member of the Editorial team will apply the relevant label to the issue or merge request in question. Points will be totaled at the end of the quarter and communicated to functional groups who exceed their budgets, so that we can work together on solutions to prevent this in the future. #### How to avoid incurring error budget points - Open an issue **as soon as you know a blog post will be needed**, using the blog post issue template, and give `@rebecca` a heads up that your post needs to go live on a specific day. - Create the MR for your blog post, ensuring everything is formatted correctly, all relevant images added, and links included. - Check the review app or preview locally to make sure everything looks as expected. - Assign the MR to `@rebecca` well ahead of time (a minimum of two working days before you expect to publish). ## Third-party posts We will promote anyone integrating with GitLab, even if we compete with them. It is very important to demonstrate to our customers that we do not lock them in. **If you are a partner or industry-adjacent third party who wants to write for our blog, please contact the [Partner Marketing](/handbook/marketing/product-marketing/#partner-marketing) team before proceeding. GitLab team members asking on behalf of a third party should do the same.** Blog posts concerning third parties or partners, whether they are to be published on the GitLab blog or externally, should follow the standard [pitching process for blog posts](/handbook/marketing/blog/#how-to-pitch-a-blog-post). As a rule, any blog post, regardless of the author, should offer some informational, educational, or entertainment value to the reader. We do not publish material that is exclusively promotional in nature. ### Guest author bio Please be sure to include a short bio of the guest author at the end of the post, using the format below: ``` ### About the guest author _Short bio describing who the author is and giving any relevant background information._ ``` You can see a [live example of a guest author bio here](/blog/2020/01/27/kubecon-na-2019-are-you-about-to-break-prod/#about-the-guest-author). ### Disclosure process for posts concerning third parties When proposing or requesting a blog post on a topic that concerns one of GitLab's business partners, it may be appropriate to seek feedback from the partner before publishing. If you are planning a blog post that discusses a partner in depth and you're not sure if it's appropriate to seek partner feedback, please ping a member of the [Partner Marketing](/handbook/marketing/product-marketing/#partner-marketing) team on your issue for their input. If they think the feedback process is necessary, please follow the steps below. **1. Connect with Alliances** When brainstorming what topic to discuss and write about, loop in a partner manager from Alliances for feedback and buy-in during the 'ideation phase'. To check who the relevant partner manager is, share your blog post issue and ask in the #Alliances Slack channel or check out our [partner dashboard](https://docs.google.com/spreadsheets/d/1-EE7vChGkDeyJxoM-LjVmUdwYwboxBmq8_42hjHGw_w/edit?usp=drive_web&ouid=100210745148351533200). At this stage you and Alliances can decide whether or not the blog post topic justifies seeking feedback from the partner in question. If so, please submit your draft blog post MR to the Editorial team for review a **_minimum_ of 5 working days before you plan to publish** to ensure enough time for all parties to review. **2. Submit draft to partner for feedback** When the merge request has been reviewed by the Editorial team, please assign the blog post MR and associated issue to the partner manager to submit the draft to our partners for review while CC'ing the appropriate stakeholders from marketing for visibility. This should be done with 48 hours' courtesy notice, for the sole purpose of providing feedback on the following areas: - Accuracy and appropriate representation of the partner in the context of the blog - Accuracy of the technical components of the blog. (i.e. If we're using the wrong CLI command or stating something inaccurate about their service/product offering) - The headline, only in cases where the partner or their product or services are named in the headline We should not proceed to publish the blog post until the partner manager has received the feedback and/or has received acknowledgment from the partner that they have read the draft within the 48-hour window. If we need to escalate within the Alliance team, @bjung is the highest escalation point within that team. **It should be noted that this is a courtesy review of the content, not a formal approval from our partner to publish the post. It should ultimately be GitLab's decision if to go live with the post or not.** ### Guest posts by GitLab partners Official [GitLab partners](/resellers) may use our [CTA button](#call-to-action) and include promotional copy, however the blog post must still serve a function (informational or educational) other than simply promoting something. For either type of guest post, the process and guidelines for publishing are as follows: 1. Create an issue in the [www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com/issues) project and label it `blog-post` and `guest/partner post`. 2. If technical input is required, we will ask for instructions from the third party; otherwise it is at the discretion of the blog editorial and technical writing teams whether or not to go forward. ### Guest posts by non-partners If the author of a guest post is not an official GitLab partner, they may link back to their website or own content with inline links, but may not include a [CTA button](#cta) or promotional copy. ### Cross posts We do not republish posts from other publications verbatim. If you spot a tweet, post, or feedback anywhere detailing an interesting use case for GitLab which you think could make a good story, open an issue and ping @kimlock to help determine whether we should pursue an interview for a blog post or case study (we will not ask the original author to create something for us). ## Pick Your Brain posts For follow-up posts to [Pick Your Brain interviews with the CEO](/handbook/eba/#pick-your-brain-meetings), as soon as an [interview](https://www.youtube.com/playlist?list=PLFGfElNsQthafBVmoPPVMvBc_Gg2nsyQb) or livestream is scheduled, please open an issue in the [gitlab.com/gitlab-com/www-gitlab-com](https://gitlab.com/gitlab-com/www-gitlab-com/issues) project, using the `PYB blog post` template, and fill out the relevant information there. The blog editorial team will assess the content of the post and decide how best to leverage it. This may mean publishing on the blog, on our Medium site, simply sharing the video on social, or something else. Once agreed, the blog team will assign and communicate the expected publish date. ## Labels - `blog post`: every blog post idea, proposal, draft, etc. **MUST** have this label - `priority`: blog posts that should be worked on immediately (please provide a rationale in your issue description) - `Blog::Pitch`: blog post ideas that are waiting for triage - `Blog::Planning/in progress`: accepted pitches and blog posts that are assigned to a member of the Content Marketing/Editorial team - `Blog::Review`: blog posts that are ready for an editorial review - `Blog::Freeze`: blog post is being reviewed by the Editorial team. No additional changes should be made until the label is lifted. - `Blog::Waiting for author`: blog posts that have been reviewed by the Editorial team and assigned back to the author to address feedback or approve for scheduling - `Blog::Scheduled`: Blog posts that have completed reviews and are scheduled for publishing - `Guest/Partner post`: blog posts that are authored and submitted from a contributor outside of GitLab - `customer story`: blog posts that include a customer interview - `CEO interview`: blog posts submitted by the GitLab CEO and require their subject matter expertise - `Content hack day`: blog posts that have been accepted from the Content Hack Day project. ## Publishing schedule With the exception of time-sensitive announcements and news, we are aiming to have blog posts scheduled two weeks ahead. - We will publish 2-3 posts per week, aiming to have a variety of topics covered within the same week. - We will stagger publishing, generally avoiding posting on Fridays and in the last few days of the month. - We don't consider operational posts (patch release announcements, for example) as conflicting with other publishing, so we may publish a post on the same day that one of those goes live. - We aim to ensure that posts that are likely to be popular are live in time to be included in the bi-weekly newsletter that goes out on the 10th and 25th of each month. ## Blog calendar The calendar below documents when posts will be published, as well as industry awareness days and anniversaries we may cover. Please bear this in mind when requesting a specific publish date for a post. _Please note that all dates are subject to change to accommodate urgent posts and announcements._ ## Writing blog posts – best practices Based on an [analysis of the traffic to blog posts from Q4 2019](https://docs.google.com/spreadsheets/d/1UzxsrnVVBUYx2Jrznj6Y4iDhWA4x4GaN0NGn2L01SO0/edit?usp=drive_web&ouid=113436756933099280536), it's clear that technical/actionable/how-to content attracts the most blog readers and thus should be the focus of the majority of the content we create for the blog. ### Think of our audience first When writing a blog post, please keep the reader in mind. This person has more than likely searched for a topic or a trend and is looking for comprehensive content with a clear takeaway. Write to this person and consider the tone and the language that will best get your point across. Our "[How to get your blog post pitch accepted](#how-to-get-your-blog-post-pitch-accepted)" section has some tips and prompts to help you prioritize our audience when planning your blog post. ### Best practices for specific types of posts #### GitLab or industry events We conducted [an audit of all event-supporting content for 2018-19 and shared the results](https://gitlab.com/gitlab-com/marketing/corporate-marketing/issues/1588). Below is a summary of the takeaways: - It's still important to keep the reader in mind when considering writing about industry events. - Live coverage of an event does not tend to draw much traffic either at the time of the event or in the months that follow. - For example, KubeCon may have been an amazing event, but it will have been covered by media everywhere. - Straightforward event recaps (whether an industry or GitLab-specific event) do not perform well. - We've seen the strongest performance from event-supporting content in the form of engineering stories based on a talk or workshop from an event. - These get traffic even if they are published weeks or months after the event because they are standalone stories. **Recommendations**: What matters to _our_ readers is what matters to GitLab. A better way to cover events that offers something new with a specific angle is to take one trend or session and do a deep dive on it, rather than trying to cover the conference as a whole. If you want to share photos from the event such as the GitLab booth or social events, consider sharing these on social channels or writing a post for the [Unfiltered blog](/handbook/marketing/blog/unfiltered/). ### Trends *From [2018 blog analysis](https://gitlab.com/gitlab-com/marketing/content-marketing/issues/248) conducted in 2018-10 1. Average sessions per month on the blog: ~30,000 1. Average sessions per post in published month: 3,792 1. Average sessions per content marketing post in published month: 3,500 1. 55% of posts get <1,000 sessions in a month 1. 27.47% of posts hit our expected outcome of 1,000-4,999 sessions in published month 1. 28.57% of posts garner less than 499 sessions in published month 1. 9% of posts are "hits" (10K+ sessions in published month); "Hits" don't consistently perform well over time **Breakdown by category of "hits":** - Content: 37.5% - Product: 31.35% - Corporate: 25% ### Observations 1. There is not a strong correlation between # of sessions and topic 1. Strong performing content marketing posts focus on show and tell engineering stories 1. Posts really fall into the 5,000-9,999 session bracket (3.3%) 1. Content hack day posts tend to perform well (>1,000 sessions in published month) ### Identifying and qualifying a high-performing blog post **Qualifying story ideas:** Look for the following patterns: 1. Team implementing a new technology, process, or coding language 1. Deep dive into how a popular feature is made 1. Chronicling a performance improvement 1. Covering a controversial decision that was made **Who and how to interview:** 1. Contact the technical subject matter expert. This can be someone who created the issue, or managed the project. 1. Set up a 30 minute interview and dig into: - What was the challenge? - What was the solution? - How did you go from point a to point b? Walk me through your thought process. - How was the solution implemented and what is a realistic use case of the solution? - What lessons were learned? - How did this make the GitLab product / development community better? 1. Optional: Contact the business subject matter expert. This could be a product manager or a product marketing manager. 1. Set up a 30 minute interview and dig into: - How does this solution help a user? - What business value does this solution bring? - How does this solution relate to our product? ### Attributes of a successful blog post: 1. Deep dive into a hard technical challenge. 1. A behind-the-scenes look at how we tackled something: "How we built x," "How we solved y," "How we scaled z." 1. Puts the reader in the shoes of the person who faced the challenge; reader learns via compelling example. 1. Intellectually satisfying; learning component. 1. Allows the reader to learn from someone else's mistake, and follows a problem/trials and triumphs/solution story arc. 1. Taking a controversial or unpopular stance on a topic, backed by hard evidence. ### Examples of high-performing posts (20K+ sessions in published month): 1. [Meet the GitLab Web IDE](/blog/2018/06/15/introducing-gitlab-s-integrated-development-environment/) 1. [How a fix in Go 1.9 sped up our Gitaly service by 30x](/blog/2018/01/23/how-a-fix-in-go-19-sped-up-our-gitaly-service-by-30x/) 1. [Hey, data teams - We're working on a tool just for you](/blog/2018/08/01/hey-data-teams-we-are-working-on-a-tool-just-for-you/) 1. [Why we chose Vue.js](/blog/2016/10/20/why-we-chose-vue/) 1. [How we do Vue: one year later](/blog/2017/11/09/gitlab-vue-one-year-later/) Team members can also browse the [Content Marketing Dashboard](https://datastudio.google.com/open/1NIxCW309H19eLqc4rz0S8WqcmqPMK4Qb) to see more examples of current blog posts drawing high traffic. ### Conducting a blog analysis Pull information on all blog posts to document how many sessions each post received in the month, and how many sessions they received of all time. Categorize them by type, bracket, total sessions in month, total sessions to date, category, theme, and topic. Eventually add first touch point revenue data. Search Google Drive for `Blog Performance` to find the appropriate sheet to work from. - Blog post links should be added as they are published and category, audience, theme, and topic should be filled out. - The Managing Editor and Manager, Content Marketing should review last month on the 1st of the month to fill out session information and make observations - Review 1st of each quarter to update total sessions **Column explanations:** - Type: helps identify the frequency of which certain types of information is shared on our current blog - Bracket: helps quickly sort blog posts by performance level - Category: indicates class of information - Total sessions in month: how many sessions the post received in the month it was published - Audience: indicates who we expect to reach - Theme: indicates the structure of the post - Topic: indicates the main subject covered ### Preparing confidential blog posts In the event that we have a big announcement to make and the information must remain confidential until, use the forked project `https://gitlab.com/gitlab-com/marketing/www-gitlab-com` to prepare your merge request. ## Publishing natively on LinkedIn and Medium Occasionally, some blog posts are better suited to publishing natively by the author on LinkedIn, or on [Medium](https://medium.com/@gitlab). We reach slightly different audiences on these channels, and some content will get better exposure and reach if published there. If you submit a blog post and the content team decides it's a better fit for one of these, we will let you know. For now, we will treat this segmentation as an experiment, monitor the performance of different types of content on different channels, and apply our learnings. We may then be able to start planning content for specific outlets and commission stories accordingly. ## Formatting guidelines Please see the [publishing process](/handbook/marketing/blog#publishing-process) before you get started. To publish to the blog, you will need to create a merge request for the www-gitlab-com project with a file of your blog post content formatted in Markdown. Please read through the [Markdown guide](/handbook/engineering/ux/technical-writing/markdown-guide/) for reference. If you like, you can start by drafting your post in a Google Doc (feel free to make a copy of this [blog post template](https://docs.google.com/document/d/1TavHlYbHQ8U1C82TEzcYaLS9l0sm89jEcBNQ0gBgkcw/edit)). Below are instructions for formatting the content of your file correctly. If you already have your content ready to go, you can jump ahead to see [how to add your blog post file with a merge request](#when-your-post-is-formatted-and-youre-ready-to-create-your-merge-request). ### Frontmatter The post **frontmatter** is the first part of any post. It is standard and cannot be changed, so please make sure to provide the correct information, and do not add nor remove anything from the default template. If you think one of the fields is unnecessary for your post, leave it blank and the editor who reviews your post may remove it. ```yaml --- title: "This is the post title" author: Firstname Lastname # if name includes special characters use double quotes "First Last" author_gitlab: GitLab.com username # ex: johndoe author_twitter: Twitter username or gitlab # ex: johndoe categories: company image_title: '/images/blogimages/post-cover-image.jpg' description: "Short description for the blog post" tags: tag1, tag2, tag3 cta_button_text: 'Watch the XXX release webcast live!' # optional cta_button_link: 'https://page.gitlab.com/xxx.html' # optional guest: true # required when the author is not a GitLab Team Member or there is more than one author ee_cta: false # required only if you do not want to display the EE-trial banner install_cta: false # required only if you do not want to display the 'Install GitLab' banner twitter_text: "Text to tweet" # optional; If no text is provided it will use post's title. featured: yes # reviewer should set postType: content definition # i.e.: content marketing, product, corporate merch_banner: merch_one merch_sidebar: merch_one --- ``` More information about each field can be found below. #### Title Please see the [style guide](/handbook/marketing/corporate-marketing/content/editorial-team/#headlines) for advice on choosing a headline that will grab readers' attention and make your post easy to search for. #### Author Write out the author's name here. If you want to credit multiple authors please use the following format: `Anthony Davanzo and Kelly Hair` (see a [live example of multiple authors](/blog/2019/09/17/gitlab-hashicorp-terraform-vault-pt-1/)) Please include the `guest: true` field in the frontmatter as well. #### Cover image Please [see below for instructions on sizing, formatting, and storing images](#images-and-illustration). ##### Stock photography Choose one from any public domain resource. [Unsplash](https://unsplash.com/) is our preferred resource for public domain images. Please [add a reference](#image-attribution) to the cover image source, owner, and license at the end of the blog post, even if it doesn't require attribution. ##### Inclusive photos We try to keep images on the blog neutral in terms of gender, ethnicity, etc. This generally means avoiding using stock images of people. It is also better to avoid using images of people (for example, GitLab team members at an event) for the cover photo because the blog post title and description overlay the image, which can look too busy. ##### Original images If you prefer, you can [create an image](#artwork). ##### Images for integration posts If the blog post is about an integration, please request a custom cover image ahead of time by pinging @luke on the blog post issue or MR. If you have or can source the integration partner's logo, it's helpful to attach or link to it in your comment. ##### Default cover image In the absence of a custom cover image, you can use the default, but please only do so where there is genuinely no other option, or if making an important, operational announcement. - GitLab Default: `'/images/default-blog-image.png'` (purple background and the Tanuki logo) #### Featured Add `featured: yes` to the frontmatter of a post to create a featured post. The most recent featured post will be shown at the top of the blog in the featured section (even if more are tagged). To remove a post from being featured, remove the `featured: yes` line from the frontmatter. #### Categories Use only **one** of the following categories per post. **Do not** change the capitalization, spelling, or anything else, otherwise you'll create another category, which is something we don't want to do accidentally. If you're not sure which category your post belongs in, just put a placeholder in your MR and leave a comment for your reviewer noting that. - `engineering` – technical, actionable content. Anything covering how to do something, use something, or solve a problem should fall under this category - `open source` – stories from or about our community, users, or the wider open source community - `culture` – posts about remote work, working together, or GitLab culture - `insights` – industry, data, newsjacking, developer survey, etc. - `company` – company announcements, news, or events - `security` - security-related posts - `unfiltered` – posts on [GitLab Unfiltered](/handbook/marketing/blog/unfiltered/) - `releases` - release posts, security and patch releases, operational product updates or announcements of changes affecting users. If you need to communicate something important to users (i.e. not a tutorial, feature post, technical deep dive, etc.), please use the `releases` category, as some users subscribe to this category for important updates and may not visit the rest of the blog. Posts in the `releases` category need to be in the `source/releases/posts` directory, not `sites/blog/source/blog/blog-posts`. Please see the [Release Post handbook](/handbook/marketing/blog/release-posts/) for more. We're working on improving category pages and tagging, but for now you can find posts under the same category by navigating to `https://about.gitlab.com/blog/categories/category-name/`. Dashes will be automatically added to multi-word categories and all of them will be lowercased in the URL. For example, the category "company" will be available under `https://about.gitlab.com/blog/categories/company/`. Note that there's a CI test that checks for wrong or missing categories. If one of the above should change or a new category is added, don't forget to edit the following files: 1. [`Rakefile`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/Rakefile) (search for `CATEGORIES`) - responsible for the CI test 1. [`source/includes/blog/category-nav.html.haml`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/includes/blog/category-nav.html.haml) - responsible for the categories navbar 1. [`source/handbook/marketing/blog/index.html.md`](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source/handbook/marketing/blog/index.html.md) - the handbook which you're currently reading 1. If a category changes, you need to replace it in all posts. Here's a one-liner command you can run: ```sh find .sites/blog/source/blog/blog-posts -type f -exec sed -i 's/categories: old/categories: new/' {} \; ``` where `old` is the old category and `new` is the new one. 1. In case of a category change, a redirect should be added in (internal). This is the last step after all the above are merged into `master` and deployed. Ask a production engineer to help you. #### Description The [`description`](https://moz.com/learn/seo/meta-description) meta tag is important for SEO, and is what appears on the [blog index page](/blog). It is also part of Facebook Sharing and Twitter Cards. We set it up in the [post frontmatter](#frontmatter), as a short summary of what the post is about. Description is limited to 150, otherwise the text will be cut off on the index page. It is mandatory for all the new posts, and it has been included in the default post frontmatter generated by [the command `rake new_post`](#create-a-new-post). #### Tags These are included to help readers find similar posts if they are interested in a particular subject. Tags appear at the bottom of each blog post, and clicking on a tag takes you to [/blog/tags](/blog/tags.html) where you can view all tagged posts and browse by tag. You can include as many tags as you like, separated by commas. Please only include tags from the following list, and note that they are case sensitive. If you think a tag should exist that isn't on this list, please leave a comment for the reviewer on your MR saying which tag you'd like to use and why it should be included. - agile - careers - CI/CD - cloud native - code review - collaboration - community - contributors - demo - design - developer survey - DevOps - events - features - frontend - Group Conversations - git - GKE - google - growth - inside GitLab - integrations - kubernetes - news - open source - patch releases - performance - [pick your brain](/handbook/eba/#pick-your-brain-meetings) - production - releases - remote work - security - security releases - security research - startups - testing - UI - user stories - UX - webcast - workflow - zero trust #### GitLab Commit tags In addition to the tags above, we also have tags for GitLab Commit events. If you want your blog post to appear on the relevant post-event GitLab Commit landing page, add the relevant tag to the frontmatter in the `tags` field. New tags will be added for each year of GitLab Commit. - brooklyn-2019 (post will display on [about.gitlab.com/events/commit/brooklyn](/events/commit/brooklyn/)) - london-2019 (post will display on [about.gitlab.com/events/commit/london](/events/commit/london/)) - sanfrancisco-2019 (post will display on [about.gitlab.com/events/commit/sanfrancisco](/events/commit/sanfrancisco/)) #### Call to action The CTA entry is optional; if you don't need to add any CTA to the hero, just omit both entries, leaving the frontmatter without them. Do not include any UTM parameters in the link. Always wrap their values with quotes. The final result is a red button over the cover image of the post. In the below example, the following was included in the blog post's [frontmatter](/handbook/marketing/blog/#frontmatter) in order to generate the CTA button. `cta_button_text: 'Watch the 8.16 release webcast live!'`
`cta_button_link: 'https://www.youtube.com/watch?v=iYPhXm8RlxI'` ![Hero CTA preview](/images/handbook/marketing/hero-cta.png){:.shadow} #### EE trial banner To not display the EE trial banner on the blog post, set `ee_cta` to `false` in the frontmatter. It is set to true by default, so there's no need to add `ee_cta: true` to the frontmatter. Only set to false on the rare occasion you have a strong reason to not display the banner (usually in the case of posts that are for developers and our open source community). #### Post type We use these to make it faster to track the effectiveness of different types of blog posts. There are three post type categories we use to differentiate blog content: 1. **Content marketing:** Examples, education, reporting, storytelling, thought leadership, and use cases. 1. **Corporate:** Company news, announcements, and community updates (ex: issue bash, contributor profiles). 1. **Product:** Release posts, critical updates, and partnership announcements. Use the `postType` frontmatter option to set the content definition. ### Media embeds We limit media embeds to the following providers: - **YouTube** for video - **CodePen** for code samples - **Google Docs** for collaborative text - **Google Sheets** for sharing spreadsheets - **Google Slides** for sharing slides ### Newsletter sign-up form We can now embed a CTA for readers to sign up for our newsletter directly from the blog post page. There are two different designs. Use the following: ``` <%= partial "includes/blog/content-newsletter-cta", locals: { variant: "a" } %> ``` Result: ![Newsletter sign-up CTA variant A](/images/handbook/marketing/newsletter-cta-a.png){: .shadow} OR ``` <%= partial "includes/blog/content-newsletter-cta", locals: { variant: "b" } %> ``` Result: ![Newsletter sign-up CTA variant B](/images/handbook/marketing/newsletter-cta-b.png){: .shadow} Note: this only works for blog post files with the extension `.html.md.erb`. ### Click to tweet Consider adding pull quotes as click-to-tweet boxes, to encourage and make it easier for readers to share key points from your blog post. This only works for blog post files with the extension `.html.md.erb`. To add a click-to-tweet box, copy the below partial and enter the `text` and `author` fields. If the author doesn't have a Twitter account you can use `gitlab` instead. `<%= partial "includes/blog/tweet", locals: { text: '', author: '' } %>` Example: ``` <%= partial "includes/blog/tweet", locals: { text: 'The Operations experience then should really just be that I go to work in the morning and see an email summary of what has happened, without me having to do anything', author: 'MarkPundsack' } %> ``` Renders: ![Click to tweet](/images/handbook/marketing/click-to-tweet.png){: .shadow} ### Merch banner and sidebar These should be included by default on all blog posts. Use your discretion; if it doesn't seem appropriate to include merchandizing on a post (for example, if we're announcing a partnership or integration, if the blog post contains lots of images and a sidebar could distract from the content, or if the blog post is very technical in nature (a tutorial or post describing a security advisory, offensive security practices, etc) and merchandizing undermines the authenticity or intent of the content or author, you can leave out either the sidebar or both the sidebar and banner. There are two steps to include these: Designate what merch sidebar and banner to add in the front matter [example frontmatter above](/handbook/marketing/blog/#frontmatter), and add the merch sidebar inside your content: #### Merch sidebar To add a merch sidebar to your blog post, you need to designate it in the front matter and include the follwing inside the content where you want the sidebar to appear. `<%= partial "includes/blog/blog-merch-sidebar-dynamic" %>` #### Merch banner Merch banners are automatically added to the end of blog posts if they are designated in the frontmatter. You can see a live example of the merchandizing in this blog post: [Introducing Resource Groups](/blog/2020/01/21/introducing-resource-groups). You can also [view the raw file of our example post](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/source%2Fblog%2Fposts%2F2020-01-21-introducing-resource-groups.html.md.erb) to see how all the necessary elements have been added to the frontmatter and body of the post. #### Current merch items Merch items are defined in one data file and implemented accross all blog posts during the build process. You can see all current merch items in [blog_merch.yml](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/data/blog_merch.yml) ``` blog-merch.yml merch_one: destination_url: "/resources/guide-to-the-cloud/" cta_text: "Learn more" banner_image_source: "/images/merchandising-content/mc-guide-to-app-security-ebook-vertical.png" banner_body_title: "Guide to the Cloud" banner_body_content: "Harness the power of the cloud with microservices, cloud-agnostic DevOps, and workflow portability." sidebar_image_source: "/images/merchandising-content/mc-guide-to-app-security-ebook-horizontal.png" sidebar_body_title: "Guide to the Cloud" sidebar_body_content: "Harness the power of the cloud with microservices, cloud-agnostic DevOps, and workflow portability." merch_two: destination_url: "/compare/github-actions-alternative/" cta_text: "View now" banner_image_source: "/images/merchandising-content/mc-mastering-cicd-vertical.png" banner_body_title: "Master your CI/CD" banner_body_content: "Watch this webcast and learn to deliver faster with CI/CD." sidebar_image_source: "/images/merchandising-content/mc-mastering-cicd-horizontal.png" sidebar_body_title: "Master your CI/CD" sidebar_body_content: "Watch the webcast" merch_three: destination_url: "/resources/ebook-single-app-cicd" cta_text: "Learn more" banner_image_source: "/images/merchandising-content/benefits-of-single-app-cicd.jpg" banner_body_title: "Free eBook: The benefits of single application CI/CD" banner_body_content: "Download the ebook to learn how you can utilize CI/CD without the costly integrations or plug-in maintenance." sidebar_image_source: "/images/merchandising-content/benefits-of-single-app-cicd.jpg" sidebar_body_title: "Single application CI/CD" sidebar_body_content: "How to reduce costly integrations and plug-in maintenance." merch_four: destination_url: "/resources/ebook-ciso-secure-software/" cta_text: "Get the eBook" banner_image_source: "/images/merchandising-content/mc-10-steps-every-ciso-ebook-vertical.png" banner_body_title: "10 Steps Every CISO Should Take to Secure Next-Gen Software" banner_body_content: "Understand three software shifts impacting security, and the steps CISOs can take to protect their business." sidebar_image_source: "/images/merchandising-content/mc-10-steps-every-ciso-ebook-horizontal.png" sidebar_body_title: "10 Steps to secure next-gen software" sidebar_body_content: "Learn how DevOps will impact your security program." - name: merch_five destination_url: "/webcast/cloud-native-transformation/" cta_text: "Learn more" banner_image_source: "/images/merchandising-content/cloud-native-transformation.png" banner_body_title: "A Cloud Native Transformation" banner_body_content: "Learn how Ask Media Group modernized their architecture and development with microservices, containers, and Kubernetes." ``` ### Comments Comments are present in all posts by default. Set it to false only if you have a strong reason to do so (`comments: false`). They are our best source of feedback on posts. ### Adding code blocks Below are the two types of code blocks we commonly use on the blog. Find a number of other options in the [Markdown guide](/handbook/engineering/ux/technical-writing/markdown-guide/#code-blocks). #### In-line code We use this for short words or phrases included in a paragraph. For inline code, surround the word or code with single backticks (`). **Example:** This is an ``` `in-line` ``` code block. **Results in:** This is an `in-line` code block. #### Fenced code blocks "Fenced" code blocks look like the block below. We use these for longer code snippets. To create a fenced code block, put triple backticks on one line directly above and one line directly below the code. **Example:** ![how to create fenced code block](/images/handbook/marketing/fenced-code-example.png){: .shadow.small.left} **Results in:** ``` this is my code block here's another line end ``` #### Highlighted code Syntax highlighting helps make code easier to read. In order to enable syntax highlighting please append the language type at the end of the code block. The name matters because every language is highlighted differently. **Example (not highlighted):** ``` ```code goes here``` ``` ``` document.querySelectorAll('a[href^="#"]').forEach(elem => { elem.addEventListener('click', e => { e.preventDefault(); let block = document.querySelector(elem.getAttribute('href')), offset = elem.dataset.offset ? parseInt(elem.dataset.offset) : 0, bodyOffset = document.body.getBoundingClientRect().top; window.scrollTo({ top: block.getBoundingClientRect().top - bodyOffset + offset, behavior: "smooth" }); }); }); ``` **Versus (highlighted javascript):** ``` ```code goes here```javascript ``` (or other languages/syntaxes such as yaml, ruby, sql, etc) ```javascript document.querySelectorAll('a[href^="#"]').forEach(elem => { elem.addEventListener('click', e => { e.preventDefault(); let block = document.querySelector(elem.getAttribute('href')), offset = elem.dataset.offset ? parseInt(elem.dataset.offset) : 0, bodyOffset = document.body.getBoundingClientRect().top; window.scrollTo({ top: block.getBoundingClientRect().top - bodyOffset + offset, behavior: "smooth" }); }); }); ``` ### Images and illustration Blog images are stored in the `source/images/blogimages/` directory. If your post contains many images, create a sub-directory for your post: `source/images/blogimages/name-of-post/`. #### Preparing images - If creating an original cover image, crop it in a 1.7 width/height pixel *proportion* (ideally 1275px x 750px). - If using an existing image for the cover (e.g. stock photography), if it is in landscape format you may not need to crop it. Please check the blog post preview locally or in the review app to ensure the image appears as expected. - All images should be less than 1MB. JPEGs tend to be smaller than PNGs so use JPEGs when possible. You can compress images using [TinyPNG.com](https://tinypng.com/) or any other image editor. - To resize in Preview go to `Tools`, `Adjust size` and adjust the entry in the `Resolution` field. Preview will estimate what the resulting image size will be before you click `OK` to confirm. - Keep all the images the same width. #### Image attribution The only images accepted for about.GitLab.com are public domain images and screenshots. Whenever you choose an image which is not a screenshot, add a link to the original image to the merge request description and as an HTML comment: ```html ``` Do the same for [cover images](#cover-image), adding a link to the original image to the end of the post: ```md Cover image by [owner name and surname](link) on [Unsplash](link) {: .note} ``` You can paste this from the box that appears on Unsplash when you have downloaded an image. For images not from Unsplash: ```md [Cover image](link-to-original-image) by [owner name and surname](link), licensed under [CC X](link-to-licence) {: .note} ``` #### Inline images To add an image inline, insert the following into your markdown file, where you want the image to appear: ```md ![Alt text for your image](/images/blogimages/your-image-filename.jpg){: .shadow} ``` The alt text for your images should describe the content and function of your image for visitors using a screen reader. #### Sizing and aligning images There are new classes for sizing and positioning blog post images. They should be added to blog post images similar to how the `shadow` class is added already: ``` md ![Your image alt text](/images/blogimages/your-image-filename.jpg){: .shadow.small.left.wrap-text} ``` The new classes are grouped into: **Size** - `.medium`: Display image 75 percent of page width - `.small`: Display image 50 percent of page width **Position** - `.left`: aligned left (default) - `.center`: centered - `.right`: aligned right **Effect** `.wrap-text`: Only applies to images that are positioned left or right. Makes text wrap around the image. These classes are only applied for screens 992px wide and wider. If a Position class is used without an Effect class then there will simply be empty space where the image isn't. Similarly, using a Position class without a Size class will have little-to-no effect. #### Image captions Insert the following beneath an inline image to include a caption: ``` This is my image caption {: .note.text-center} ``` This will look as below: This is my image caption {: .note.text-center} #### Screenshots For technical/tutorial posts, please illustrate your examples with [code blocks](#adding-code-blocks) or screenshots. Be consistent with your examples. E.g., if you are using a generic URL to exemplify your steps `domain.com`, be consistent and keep it `domain.com`, throughout the post. - Static images should be used to illustrate concepts, provide diagrams, elements of the UI or orient the reader. - Images should not be used to render commands or configuration which would prevent someone being able to copy and paste. - Animated GIFs can be used sparingly where you need to show a process or some event happening over the course of time or several actions, though they should not replace text descriptions or instructions. - Use screenshots to identify and localize specific parts of the screen. There are great tools for doing so. For example, Nimbus Screenshot (browser extension), Mac screenshot, Snipping Tool for Windows, and Screenshot Tool for Ubuntu. **Important security point:** Do not expose your personal details by using your real tokens or security credentials. Use placeholders such as `[project's CI token]` stub instead. Or blur them if displayed on screenshots. #### Embedding videos Please see the [Markdown Guide](/handbook/engineering/ux/technical-writing/markdown-guide/#display-videos-from-youtube) for instructions for embedding videos from YouTube and other sources. If appropriate, please add a video credit, for example: ``` Video directed and produced by [Aricka Flowers](/company/team/#arickaflowers) {: .note} ``` #### Embedding tweets or Instagram posts Please see the [Markdown guide for instructions for embedding posts from social media](/handbook/engineering/ux/technical-writing/markdown-guide/#embed-tweets). #### Creating GIFs Animated GIFs are very useful to illustrate short dynamic processes, which might be easier to understand with this kind of resource. There are a few ways to create animated GIFs, one of them is using [Giphy Capture], a light-weight app for Mac. Avoid GIFs with a huge file size, they will be difficult to load for users with bad internet connection. In those cases, you can either cut the GIFs in smaller pieces, or record a video, or use a sequential image. Read more on Making Gifs in the Product Handbook. #### Artwork If you create your own cover image, it should have the following proportions: - On the [blog landing page](/blog): 1275px x 750px w/h = 1.7 - On blog post page (widescreen): 1920px x 550px w/h = 3.5 Try to have them harmonically aligned with the title, which overlays the background image in both cases. To crop the image, use the size of 1275x750 px. If you want to align the background image with the title overlay, use the widescreen proportion. ## When your post is formatted and you're ready to create your merge request You can go about this a couple of ways: by adding a new file to `sites/blog/source/blog/blog-posts/` in the UI, or using the terminal on your own computer. ### Creating a blog post MR from the UI You should have an issue for the blog post you are writing. Go to the issue and click `Create merge request`. ![Create merge request button](/images/handbook/marketing/create-mr-screengrab.png){: .shadow.medium.center} Now you have a merge request! Please edit the title to be "WIP: blog post - Title of blog post". Placing "blog post" in your MR title will trigger a blog-only build for review apps, which means you will be able to preview your blog post much sooner. Make sure you select the blog post template for your MR, as this contains some important tasks for you to complete. ![MR template for blog post](/images/handbook/marketing/blog-mr-template.png){: .shadow.medium.center} You can assign the MR to yourself while you are working on it. Click on the link to the right of `Request to merge` (this is the name of your branch). ![branch name](/images/handbook/marketing/branch-name-screengrab.png){: .shadow.medium.center} Now navigate to `sites/blog/source/blog/blog-posts/` in the tree view, then click on the `+` dropdown menu and select `New file`. ![New file](/images/handbook/marketing/new-file.png){: .shadow.medium.center} Enter your filename using the format `yyyy-mm-dd-name-of-your-post.html.md.erb`. This will become the URL for the blog post so please keep that in mind and don't use something like `my-blog-post-draft`! 😄 ![New file](/images/handbook/marketing/enter-filename.png){: .shadow.medium.center} Please do not include special characters, capital letters, or numbers (other than the date) in your filename as this can lead to issues with publishing and can break the link to your review app. {: .alert .alert-gitlab-orange} If you aren't sure when the post will be published, just choose an arbitrary date in the future – we will update it before publishing. Now you can paste your post content into the window. If pasting from a Google Doc or another word processor, please make sure you convert it to plain text first. A quick way to do this is to paste everything into the URL bar of a browser, and paste it into your blog post file from there. ![Example blog post file](/images/handbook/marketing/example-blog-post-file.png){: .shadow.medium.center} Note that there is no blank line at the top or lines in between your front matter items. {: .note.text-center} When ready, scroll down and enter a description of what you've just done in the `Commit message` box. Make sure the `Target branch` is correct (i.e. has the number and title of the issue for your blog post) then click `Commit changes`. ![commit message](/images/handbook/marketing/commit-message.png){: .shadow.medium.center} You will then see your added file. To go back to your MR, it's easiest to go to your MRs in your dashboard (this is why it's important to assign the MR to yourself when you create it). You'll find all MRs assigned to you in the top right corner of your screen. ![MR dashboard](/images/handbook/marketing/mr-dashboard.png){: .shadow.medium.center} In your MR, if you scroll down and go to the `Changes` tab, you should see the blog post file you added there. ![Changes tab](/images/handbook/marketing/changes-tab.png){: .shadow.medium.center} To see a preview of your post as it will look when it's live, you will need to wait for the pipeline to pass. You can check its progress from the `Pipelines` tab. When it passes, you can click on `View app` near the top of your MR and it will open a new tab with your preview. **Please check your review app before asking anyone else to review.** ![Link to review app](/images/handbook/marketing/review-app-link.png){: .shadow.medium.center} If the blog post pipeline fails, it will suggest you retry, but the merge button will not be clickable. Instead, click on the red (failed) icon on your pipeline and you will see a list of builds with the failed ones on top. Click on the "retry" icon on the right to re-run the build. If you need to make changes to your file, you can edit it by clicking on the edit button, which will take you to the same interface as when you added your new file. Just make your changes, edit the commit message to say what you did and hit `Commit changes`. ![Edit button](/images/handbook/marketing/edit-file.png){: .shadow.medium.center} When you're ready, assign the MR to a fellow team member to review your post. When they have reviewed and you've addressed any comments they had and resolved any outstanding discussions, please assign your MR **and the corresponding issue** to `@rebecca` to review. You may find this video walkthrough helpful for creating your blog post MR from the UI:
### Creating a post from the command line You will need to be set up to edit the website locally in order to create your post this way. Please see [GitLab 102](/handbook/marketing/product-marketing/getting-started/102/) for instructions. If you're already set up: - Run `git checkout master` - Run `git pull` to ensure your version of master is up to date with GitLab.com - Run `git checkout -b new-branch-name` (substitute `new-branch-name` with whatever you want to call your branch) - Now run ```sh rake new_post ``` Hit **enter** or **return**, then you'll be prompted to enter the post title. Type in the title exactly as you want it, for example "Hello World – I'm a new post" and rake will take care of the filename for you. Then you just open the file, fill out the front matter and start writing, or paste your (plain text) draft in from your Google Doc. ### Adding a cover image to your blog post MR Most blog posts require a new [cover image](#cover-image). You should upload your chosen image to the same branch as your blog post file, so that it is all included in the same MR. This means it will be published to the website simultaneously, and also allows you to preview your cover image in the review app. #### Step 1: Upload image file When you have selected an image to use, save it on your computer, ensuring you don't include any capital letters, spaces, or special characters in the filename. Now go to your MR and click on the branch name after`Request to merge`. ![branch name](/images/handbook/marketing/branch-name-screengrab.png){: .shadow.medium.center} Navigate to `source/images/blogimages/` in the tree view, then click on the `+` dropdown menu and select `Upload file` ![Upload file](/images/handbook/marketing/upload-image-file.png){: .shadow.medium.center} Drag and drop or click to upload your image file, then enter a description of what you've just done in the `Commit message` box. Make sure the `Target branch` is correct (i.e. has the number and title of the issue for your blog post) then click `Upload file`. To go back to your MR, it's easiest to go to your MRs in your dashboard (this is why it's important to assign the MR to yourself when you create it). You'll find all MRs assigned to you in the top right corner of your screen. ![MR dashboard](/images/handbook/marketing/mr-dashboard.png){: .shadow.medium.center} In your MR, if you scroll down and go to the `Changes` tab, you should see the blog post file you added there. ![Changes tab](/images/handbook/marketing/changes-tab.png){: .shadow.medium.center} #### Step 2: Add file path to blog post file Make a note of the name of your image. ![Image file name](/images/handbook/marketing/image-file-path.png){: .shadow.medium.center} Scroll down to your blog post file and click on the pencil icon (Edit file button). ![Edit button](/images/handbook/marketing/edit-file.png){: .shadow.medium.center} This will take you to the same interface as when you added your new file. In the frontmatter, look for this field: ``` image_title: '/images/blogimages/post-cover-image.jpg' ``` Change the image filename to the name of the image you just uploaded. Ensure that you keep the whole path the same (so, starting with `/images/blogimages/`). Now edit the commit message to say what you did and hit `Commit changes`. Go back to your MR. If everything has been done correctly, when the pipeline passes your review app should show the cover image as expected. ![Link to review app](/images/handbook/marketing/review-app-link.png){: .shadow.medium.center} #### What if my cover image isn't showing? This is usually because the image filename and what you entered in the frontmatter do not correspond. Look out for typos in either the filename or in the frontmatter. Make sure that the image path is correct (i.e. it begins with `/images/blogimages/` – no missing slash at the front, no `source` before the first slash). It often helps to look at the file of [another recent blog post that is already live](https://gitlab.com/gitlab-com/www-gitlab-com/tree/master/sites/blog/source/blog/blog-posts) and compare it to your file to see if there are any discrepancies.