Social Media Management Dashboard in Coda


#1

One of the docs I show people frequently when explaining coda is my Social Media Tool. I built it specifically to solve some of the problems I encountered keeping track of content I’ve shared. This is a tour of some of the pages in the Coda Doc (App? Does this become an app at some point?)

Get the Template Version of this Coda Doc Here (you will need a coda account to access)


This is the landing page, explaining the doc. There’s a list of posts for people to review if they’re just looking to see the content that’s up next for posting & leave feedback. Where possible, I’ll also share formulas with y’all.

=NumberedList([Blogs for Review].sort(true, Scheduled).Title.Slice(1,3))

#2

The idea behind the landing page is to focus on links to other content. Emojis help with scanning, and make coda’s left hand nav fun to explore. To avoid showing every single blog on the planet, I use slice() on a sorted list to show only the next 3 items. Blogs for Review is a summary table of Blog Posts with filters. I’m on the fence as to either (1) adding a filter() to the formula above or (2) moving sort() over to the View of blog posts I’m referencing.


This is the heart and soul of the project. It pulls from several different tables to tell me what I need to be doing today. For every blog’s data table, there’s a series of yes/no columns and dates. From it, I can derive what needs to be posted and in what locations. For example, the Blog into AP view uses the following filter

=Today() + Days(14) >= Scheduled and ([✈️ Autopilot]=false or Header=false)

This will show me all blog posts that are being launched in 14 days that don’t lack a header or aren’t in Autopilot yet (my email automation tool). The view itself is sorted by the Scheduled column and then hidden. If it’s on the list, it needs to be done!

The pattern repeats for mailing list posts, medium / linkedin / facebook shares, and other external content. It doesn’t track posts outside of leadsv.com just because external sites often have their own editing process.


#3


What we’re looking at here is an auto-generated roadmap. Using the Selector (February), I pull matching blogs, mailing list topics, and news articles. In order to generate these, I often have to do some pretty crazy date manipulations. For example, here’s the list of blog posts based on the control. I’ve added line breaks so I can help explain what’s going on line by line.

=BulletedList([Blog Data].filter(
    Scheduled >= toDate(concatenate([Monthly Plan Picker]," 1, ", Year(today())))
    and
    Scheduled <= endofmonth(
        toDate(concatenate([Monthly Plan Picker]," 1, ", Year(today()))),0)
).Title)
  1. create a bulleted list based on blog data and reduce the results using filter()
  2. look for posts that have a scheduled greater than or equal to the first of the control’s month (Monthly Plan Picker is the control name)
  3. two clauses, because there’s not really another way to do between()
  4. look for posts that have a scheduled date less than or equal to the end of the month. We use toDate() for consistency. Later in the document, I have a section for the next month, which requires me to use toDate() with an offset of 1 month.

Once all that’s done, we can take the titles and use those in the bulleted list. The same pattern can also be used for the mailing list topics and mailing list content. This way, every moth remains on-message. Phew!


#4


This is somewhat straightforward, it’s a blog post. Until there’s a way to reference thisSection.title, I need to put a View at the top of the document and filter it down to the blog’s unique ID. If you find yourself wanting SQL-ish byId() kind of functionality, the following column in your table is a lifesaver.

=thisRow.RowId()

What this will do is generate a unique ID for every row in the table, no duplicates. This makes filtering much easier. Once I can query for a section’s title, all of the Views can go away (I can just to lookup()/filter() instead)


#5

This is how the mailing list is built. A pair of form controls show the next scheduled moment items, there’s a date picker, and a nice emoji to quickly scan and determine if I have work to do on the next newsletter or not. Subsequent views are filtered based on the date controls, and it makes adding content to a specific newsletter very quick. No fancy formulas this time. :slight_smile:


#6


Finally, every good marketing needs something called UTM tags. Used by Google Analytics and a slew of other tools, these URL parameters help you know where individuals are coming from. After all, you don’t want to spend too much time where your clients aren’t! For any given source, medium, etc, it builds out the UTM string using formulas. Conditional formatting prevents you from generating a UTM string that’s already in use somewhere else. You can check show to get a copy/paste ready version of the UTM parameters for twitter/facebook/etc.

Alright, I think that’s everything. I’d be more than happy to share more about the doc, some of the interesting formulas, or some of the weird (fun) bugs I discovered while building out this Coda.

Hope you had as much fun learning as I did building!


#7

@jakobheuser this is awesome. Would you be willing to share a version of the doc so we can explore it in more detail/fork it? Is there a way for us to make it a community created template?


#8

Sure. I’ll create a scrubbed down version to link here for folks!

Since coda is built on Google Drive, here’s how you can access someone else’s document as a coda user.

  1. follow the link to the coda doc here
  2. Choose to open the document in coda
  3. As a coda user, it should (in theory) create a copy you can use

(note, if you want to do this, you need to have access to coda, have connected the app, and have set sharing permissions for individuals outside of your domain).

Thanks for the suggestion @cnr! I also added a link to the top of the thread. And if y’all like it, don’t forget to hit the :heart: on the top of the thread.


#9

This is an awesome template @jakobheuser! I’m still trying to get a grasp of the “flow” of how you would use this tool on a weekly basis. For the views of the Blog Data table, how are you able to dynamically create view names that reference the ID of the Blog Post or Published Post? Or is this manually written in after you’ve created the view?

For instance, this is a view of the Blog Data table for ID=37, is there a way you dynamically populated the view with this name?

13%20AM


#10

@Al_Chen It requires a little bit of setup, but it’s (almost) magical.

  1. The Blog Data table links to the given section and has the unique ID via thisRow.rowId()
  2. The View of Blog Data has a manually created filter to limit the table to only the single row containing the self-referencing metadata about the current section

In an ideal world, if thisSection.sectionId() existed as a function I could call, I’d only need 1 view. I could recycle the view repeatedly, and the filter would be [Blog Data].Name = HYPERLINK(thisSection.sectionId()) For now though, the little summary tables need to be built manually.

To create a new blog post, this is the flow:

  1. Create a new section and give it a title (any title)
  2. Create a new row in Blog Data and make Title a link to the newly created section
  3. Create a view of Blog Data called ID ## Details filtered to the matching ID column. (We do this specifically so that if the title changes, we don’t break the tables)
  4. Create the header / title information for readability. Those formulas are all based on =[ID ## Details].Field. So for example, the title at the top is =[ID ## Details].Title.First()

Hope this helps, and thanks for asking about it!