[DIY] Create a categorized directory of Marketplace stores with Review pages

Hi all!

I wanted my store owners to be able to submit information about their stores so they could each have a nice dedicated ratings & review page on the main site, with a categorized directory of all stores in the network, and the option to submit premium listings as well. I also wanted all this to be done from the front-end of the main site (don't want them in the dashboard at all!), and it all needed to fit seamlessly with the overall look and feel of my site. Oof!

I did look into WPMUdev's Directory plugin, but it doesn't have a front-end editor, which was a central element of my plan, and as mentioned, I wanted it to fit the current L&F of my site. So I developed my own package using a few plugins and a bit of template customization. (OK, so I just wanted to have some fun making the thing, I'll admit it :slight_smile: )

Here's what it looks like: http://etcemall.com/blog/another-fine-store-here/
...and here's how it all came to be:

Let's first get our plugins (or you can skip straight to the template stuff below and play with plugins later)...

The first plugin required is a front-end post form. My all-around favorite is by far Gravity Forms, but any other will do fine as long as posts can be submitted to predefined categories, and you can define how and what info is to be displayed. http://www.gravityforms.com/

Next are a cool ratings plugin and a sharing plugin, both installed network-wide (again, go ahead and substitute with your own preferences):
http://wordpress.org/extend/plugins/rating-widget/
http://wordpress.org/extend/plugins/share-and-follow/

For all-around convenience in site design, I also use J-Shortcodes and/or TheTheFly plugins for buttons, tabbed content, nifty boxes and such (give them a whirl, you'll love 'em):
http://www.jshortcodes.com/shortcodes/
http://thethefly.com/wp-plugins/thethe-tabs-and-accordions/

Finally, a menu plugin so you can really show off your stuff in style (this is entirely optional, your theme's menu may be perfectly fine for you). I use a magnificent premium menu plugin called UberMenu (I'm hooked!): http://wpmegamenu.com/
... but a very adequate free alternative can be found at Design Chemical:
http://www.designchemical.com/blog/index.php/wordpress-plugins/wordpress-plugin-jquery-drop-down-mega-menu-widget/

Now to the templates we need to customize (and the whole point of this post)...

For my site, I use the Gridmarket child-theme of Framemarket, so all references here will be to templates from that theme... and that's why this post is in the Framemarket forum too :slight_smile:. If you use another theme/child-theme, the customizations can be applied to the corresponding files.

The files from Gridmarket that you'll need are:
content.php
content-single.php
category.php
comments.php
style.css

Note that although comments.php already exists in Gridmarket, you'll need to copy the first 3 files from the Framemarket parent to Gridmarket.

Let's start with the easy one. Open category.php (once you've copied it over to the child-theme of course) and replace this
<h1 class="post-title"><?php printf( __( 'Category Archives: %s', 'framemarket'), '<span>' . single_cat_title( '', false ) . '</span>' ); ?></h1>
...with this

<?php if (is_category(array(17,18,19,20))) : ?>
	<h1 class="post-title"><?php printf( __( 'Here are all our %s stores', 'framemarket'), '<span>' . single_cat_title( '', false ) . '</span>' ); ?></h1>
<?php else : ?>
	<h1 class="post-title"><?php printf( __( 'Category Archives: %s', 'framemarket'), '<span>' . single_cat_title( '', false ) . '</span>' ); ?></h1>
<?php endif; ?>

Replace the category ID's in the array on the first line and the text of the post-title with your own stuff (don't remove the %s 'cuz that's what gets the category name). This will simply ensure that posts made to your selected categories will display on custom archive pages with the heading 'Here are all our (category here) stores'

Now open comments.php and replace the following (around line 25) to customize the display of reviews - formerly known as comments - on the ratings & review pages. Replace this:
<h3><?php printf( _n( '1 response to %2$s', '%1$s responses to %2$s', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
...with this:
<?php if (in_category(array(17,18,19,20))) : ?>

<h1 class="post-title">Rave reviews for <?php the_title(); ?></h1>
	<h3><?php printf( _n( '%2$s has 1 review', '%2$s has %1$s reviews', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
<?php else : ?>
	<h3><?php printf( _n( '1 response to %2$s', '%1$s responses to %2$s', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
<?php endif; ?>

Again, replace the category ID's with your own. If you don't like the extra <h1> title I added, simply delete it or edit it. Now, to show customized labels on the comment form before any comments have actually been submitted, on line 62, replace this:
<?php comment_form() ?>
...with this:

<?php if (in_category(array(17,18,19,20))) : ?>
	<?php comment_form(array('title_reply' => "Review this store", 'label_submit' => "Submit your review", 'comment_field' => '<p class="comment-form-comment"><label for="comment">' . _x( 'Review', 'noun' ) . '</label><textarea id="comment" name="comment" cols="45" rows="8" aria-required="true"></textarea></p>')); ?>
<?php else : ?>
	<?php comment_form() ;?>
<?php endif; ?>

Remember to replace the category ID's with your own here too. Now let's get content.php open. Here we're going to customize the content for archive entries and the archive page navigation. On line 91, replace this:
<?php the_excerpt(); ?>
...with this:

<?php the_content(); ?>
	<?php if (is_category(array(17,18,19,20))) : ?>
		<span><a class="jbutton green" href="<?php the_permalink(); ?>" title="<?php printf( esc_attr__( 'Permalink to %s', 'framemarket'), the_title_attribute( 'echo=0' ) ); ?>" rel="bookmark"><?php _e( 'Read reviews', 'framemarket'); ?></a></span>
	<?php endif; ?>

Replace the category ID's with your own. This ensures that we get the whole post including a thumbnail of the primary image rather than just an excerpt of text. If you prefer just the excerpt, simply change the_content to the_excerpt. Also, notice the 'jbutton' in the link? This is one place the J-Shortcodes plugin comes in handy as it automagically adds a nicely-styled button with a permalink to the review page (we'll get to that soon, promise). Now let's have fun with the page navigation. Down at the bottom around line 130, replace this:

<div id="navigation-bottom" class="navigation">
	<div class="nav-previous"><?php next_posts_link( __( '<span class="meta-nav">?</span> Older posts', 'framemarket') ); ?></div>
	<div class="nav-next"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">?</span>', 'framemarket' ) ); ?></div>
</div>

...with this:

<?php if (is_category(array(17,18,19,20))) : ?>
	<div id="navigation-bottom" class="navigation">
		<div class="nav-next"><?php next_posts_link( __( 'Continue window shopping this way <span class="meta-nav">?</span>', 'framemarket') ); ?></div>
		<div class="nav-previous"><?php previous_posts_link( __( '<span class="meta-nav">?</span> Go back the way you came', 'framemarket' ) ); ?></div>
	</div>
<?php else : ?>
	<div id="navigation-bottom" class="navigation">
	<div class="nav-next"><?php next_posts_link( __( '<span class="meta-nav">?</span> Older posts', 'framemarket') ); ?></div>
	<div class="nav-previous"><?php previous_posts_link( __( 'Newer posts <span class="meta-nav">?</span>', 'framemarket' ) ); ?></div>
	</div>
<?php endif; ?>

Don't forget the category ID's :slight_smile: Did you notice that the direction of the 'Older' and 'Newer' posts arrows in the original code is screwed up? We just fixed that and added custom messages to display on those links when viewing store category archives. Edit them to suit the particular flavor of your site. I also like to have the navigation at the top; so if you want that too, simply add the replacement code just above line 29 where you see:
<?php while ( have_posts() ) : the_post(); ?>
Finally, and this is an optional template customization, let's open content-single.php and create a simple post-meta box to only display the store category on the review pages. We'll be hiding the actual post-meta in a moment when we get to the CSS. Just above line 7 where you see this:
<div class="post-meta">
...add this:

<div class="mycat">
	<?php if (in_category(array(17,18,19,20))) : ?>
		<?php printf( __( '<span class="%1$s">Store category: </span> %2$s', 'framemarket'), 'post-info-prep post-info-prep-cat-links', get_the_category_list( ', ' )) ; ?>
	<?php endif; ?>
</div>

There are those category ID's again! Also, feel free to give the wrapper div any name you like (I just like cats, so...).

OK, we're done with template customization, now let's get stuff looking nice! Unlike most WPMUdev child-themes, Gridmarket doesn't have a _inc/css folder. Simply open gridmarket/style.css to add custom styles. The first thing we're going to do is add some styling to ensure that all buttons that aren't jbuttons will be styled the same way (this includes Search, Buy Now, Submit, etc.). Harmony is a good thing :slight_smile: Add the following to style.css for those buttons (these styles work in dumb ol' IE too):

/*Same button style as J-Buttons*/
body input[type="submit"], .nav-previous a, .nav-next a, .reply a, a.mp_cart_direct_checkout_link, #mp-product-grid a.mp_link_buynow {
    display: inline-block;
    zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
    *display: inline;
    vertical-align: baseline;
    margin: 2px;
    outline: none;          /* remove dotted border in FF */
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    font: 14px/100% Arial, Helvetica, sans-serif  !important;
    padding: .35em .75em .4em !important;
    text-shadow: 0 1px 1px rgba(0,0,0,.3);
    -webkit-border-radius: .5em;
    -moz-border-radius: .5em;
    border-radius: .5em;
    -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
    -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
    box-shadow: 0 1px 2px rgba(0,0,0,.2);
  color: #f2fbff !important;
  border: solid 1px #0076a3 !important;
  background: #0095cd !important;
  background: -webkit-gradient(linear, left top, left bottom, from(#00adee), to(#0078a5)) !important;
  background: -moz-linear-gradient(top,  #00adee,  #0078a5) !important;
  filter:  progid:DXImageTransform.Microsoft.gradient(startColorstr='#00adee', endColorstr='#0078a5') !important;
  }
body input[type="submit"]:hover, .nav-previous a:hover, .nav-next a:hover, .reply a:hover, a.mp_cart_direct_checkout_link:hover, #mp-product-grid a.mp_link_buynow:hover {
    display: inline-block;
    zoom: 1; /* zoom and *display = ie7 hack for display:inline-block */
    *display: inline;
    vertical-align: baseline;
    margin: 2px;
    outline: none;          /* remove dotted border in FF */
    cursor: pointer;
    text-align: center;
    text-decoration: none;
    font: 14px/100% Arial, Helvetica, sans-serif;
    padding: .35em .75em .4em !important;
    text-shadow: 0 1px 1px rgba(0,0,0,.3);
    -webkit-border-radius: .5em !important;
    -moz-border-radius: .5em !important;
    border-radius: .5em !important;
    -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.2);
    -moz-box-shadow: 0 1px 2px rgba(0,0,0,.2);
    box-shadow: 0 1px 2px rgba(0,0,0,.2);
  background: #007ead !important;
  border: solid 1px #0076a3 !important;
  background: -webkit-gradient(linear, left top, left bottom, from(#0095cc), to(#00678e)) !important;
  background: -moz-linear-gradient(top,  #0095cc,  #00678e) !important;
  filter:  progid:DXImageTransform.Microsoft.gradient(startColorstr='#0095cc', endColorstr='#00678e') !important;
  }
body input[type="submit"]:active, .nav-previous a:active, .nav-next a:active, .reply a:active, , a.mp_cart_direct_checkout_link:active, #mp-product-grid a.mp_link_buynow:active {
    position: relative;
    top: 1px;
  color: #80bed6;
  border: solid 1px #0076a3 !important;
  background: -webkit-gradient(linear, left top, left bottom, from(#0078a5), to(#00adee)) !important;
  background: -moz-linear-gradient(top,  #0078a5,  #00adee) !important;
  filter:  progid:DXImageTransform.Microsoft.gradient(startColorstr='#0078a5', endColorstr='#00adee') !important;
  }

Whew, that's a lot of CSS! Wait, there's more... below is the entire set of rules I use for my review and archive pages. Notice the container class names for categories (ex: .category-featured-stores); you'll need to replace those with your own categories wherever you see them like this: .category-YOUR-CAT-SLUG-HERE
Also, some of the selectors shown below don't exist yet, because we haven't created them (we will when we get to the Gravity Forms part, hang on...)

/*Featured Stores*/
body.archive #content img { /* Will affect all archive images for site consistency. Apply category classes to only affect certain categories like stores. */
  float:left;
  max-width:150px;
  max-height:150px;
  margin-right:20px;
  width:auto;
  }
body.archive span.store-desc { /* Comment this out to show the store description in archives. */
  display:none;
  }
#content .category-featured-stores .post-meta, #content .category-featured-stores .post-info, #content .category-collectibles .post-meta, #content .category-collectibles .post-info, #content .category-clothing-and-accessories .post-meta, #content .category-clothing-and-accessories .post-info, #content .category-handcrafted-goods .post-meta, #content .category-handcrafted-goods .post-info { /* Hides the standard WP navigation on store pages */
  display:none !important;
  visibility:hidden !important;
  }
#content .category-featured-stores h2.post-title, #content .category-collectibles h2.post-title, #content .category-clothing-and-accessories h2.post-title, #content .category-handcrafted-goods h2.post-title {
  background:#eee;
  padding:5px;
  }
#content .category-featured-stores .subtitle, #content .category-collectibles .subtitle, #content .category-clothing-and-accessories .subtitle, #content .category-handcrafted-goods .subtitle {
  font-size:16px;
  font-style:italic;
  }
.single-post .category-featured-stores, .single-post .category-collectibles, .single-post .category-clothing-and-accessories, .single-post .category-handcrafted-goods {
  border-bottom:none;
  }
.optimg { /* Container class for additional store images uploaded via Gravity Forms. */
  float:right;
  margin:0 20px 0 0;
  }
.single #content .optimg img {
  max-width:150px;
  }
.archive .optimg, .archive .store-desc {
  display:none; /* Hides additional images in archive pages. */
  }
.single .category-featured-stores #navigation-bottom, .single .category-collectibles #navigation-bottom, .single .category-clothing-and-accessories #navigation-bottom, .single .category-handcrafted-goods #navigation-bottom, {
  display:none; /* Hides previous-next links on store review pages. */
  }
.archive #navigation-bottom {
  margin:20px 0;
  }
.archive #navigation-bottom .nav-previous {
  float:left;
  width:auto;
  }
.archive #navigation-bottom .nav-next {
  float:right;
  width:auto;
  }
.mycat {
  background:#f0f0f0;
  padding:0 10px;
  font-size:14px;
  }

I won't include any styling here for the other plugins I've recommended 'cuz that would likely clash with whatever look you already have going on your site.

Now to the actual submission form. As I mentioned, I use Gravity Forms for this, but you could adapt it to whatever front-end solution you have. Here's how I've set mine up:

Title field = Your store's name
Website field = Your store's URL
Single line text = Descriptive Subtitle or Tagline
Body field = Store description
Category field = Store Category (select the categories you want your users to post to here, and make sure they're the same ones you've identified in the code snippets above!)
Image field = Store Image
Image field = Optional 2nd Image
Image field = Optional 3rd Image

Right, we have our fields set up, now let's set up the form to make the magic happen for your users. First, a nice touch is to make it so that users are redirected to their store review page upon submission (unless, of course, you set the Post Status to "Draft" or "Pending Review" one of the post fields). In the Form Settings field (the first one at the top), go to the "Confirmation" tab and select "Redirect". Enter http://YOUR-SITE.com/blog/stores/ in the field. Then check the "Pass field data" box and enter this in the field that opens: p={post_id} Voilà, instant redirect to the post just created.

In the Body field, check the "Create content template" box and create a template something like this, selecting your own merge tags from the dropdown of course (notice the jbutton again... geez Louise, they're all over the place!):

{Store Image:1:medium:left}
<br /><br />
<span class="subtitle">{Descriptive Subtitle or Tagline:5}</span>
<br /><br />
<span class="optimg">{Optional 2nd Image:7:medium:right}<br />{Optional 3rd Image:8:medium:right}</span><a class="jbutton green" href="{Your store's URL:4}">Visit this store</a>
<br /><br />
<span class="store-desc">{Store description:3}
</span>
<br /><br />

Finally, create a WP page on your site (or use an existing one) and insert the form shortcode. Navigate to that page, fill out your form and watch the magic unfold.

Hope you find use for this tut. If you need help with specifics, give me a shout!

  • aecnu
    • WP Unicorn

    Greetings pcwriter,

    Beautiful, very nice indeed. I will let this ride a little while to see member responses and at minimum they can fix their arrows since to the best of my knowledge this still exists in FrameMarket/GridMarket.

    Thank you for the Tutorial and some more rep points for you.

    Cheers, Joe

  • Patrick
    • Support Monkey

    @Joe
    Thanks for the compliments. It was fun putting all this together and I thought it would be even more fun to share the fun! And thanks for the points too :slight_smile:

    @All
    I just noticed a little goof with code highlighting in the first part of the comments.php edit in the tut above. It should read like so:

    Now open comments.php and replace the following (around line 25) to customize the display of reviews - formerly known as comments - on the ratings & review pages. Replace this:
    <h3><?php printf( _n( '1 response to %2$s', '%1$s responses to %2$s', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
    ...with this:

    <?php if (in_category(array(17,18,19,20))) : ?>
    <h1 class="post-title">Rave reviews for <?php the_title(); ?></h1>
    	<h3><?php printf( _n( '%2$s has 1 review', '%2$s has %1$s reviews', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
    <?php else : ?>
    	<h3><?php printf( _n( '1 response to %2$s', '%1$s responses to %2$s', $num_comments, 'framemarket' ), number_format_i18n( $num_comments ), '<em>' . get_the_title() . '</em>' ) ?></h3>
    <?php endif; ?>

    Sorry if this causes any confusion :slight_frown:

  • cmwwebfx
    • Flash Drive

    Hi pcwriter,

    I got the email alert today about the post update, so did not get a chance to reply. This is incredibly well written, and thank you for taking the time to do this. I do not have gridmarket, but I will certainly try on my site theme for the brickworksmarket.com.au

    Ciaran

  • Patrick
    • Support Monkey

    Hi Joe,

    Lots of grief, for sure! When I first started dabbling and learning what little I know about coding, I would often wind up with a blank screen when I uploaded files. Then would spend an inordinate amount of time tracking down what usually amounted to a single unclosed tag. Since then, I've developed the habit of immediately closing a tag when opening one, before I put anything in it.

    Having a closing if tag, with no corresponding opening tag, would definitely muck up the works, and potentially cause a few newbies to lose a goodly portion of their hair... I can't even begin to imagine the barber bill for that one :slight_smile:

  • Arun Basil Lal
    • New Recruit

    @pcwriter

    Congrats on the rep points, you earned every bit of it. I got the email and I am currently checking out your profile and doing the verification.

    So glad to have you in here, you will receive an update via email soon. We will then do the honors of inviting you to the exclusive club!

    Cheers!

  • Fondeli
    • The Bug Hunter

    @pcwriter,

    I've just read through your tutorial, it is brilliant, and I am looking forward to creating a test site, just to implement this and your other tutorial. But what amazes me most of all is that you are using Gridmarket, you have truly made it your own. I do have a question, which I have asked before, but I am hoping you may have an answer for me. What file do I need to edit to be able to add something to the front page of Gridmarket? I want to add a recent posts slider, or even better would be using the Tabs plugin that you have used.

    Thanks! :slight_smile:

    Also congrats on the lifetime membership...well deserved!

  • Patrick
    • Support Monkey

    @Fondeli

    If you're using Gridmarket and have your Store or Products page set as the frontpage (under Settings > Reading), your kinda out of luck as the settings (under Products > Store Settings > Messages) is buggy are the moment.The theme designer has been notified. See this post for more: https://premium.wpmudev.org/forums/topic/final-advice-required-for-buy-product-page#post-203252

    Cheer up: there is an easy workaround though... I just love workarounds :slight_smile:

    Simply create a WP page and select that in Settings > Reading at "Front page displays". Now you can add whatever your heart desires to that page, however you want.

    If you want a great selection of brilliant premium sliders (between $6 and $9each) that can be inserted pretty much anywhere via widgets, templatetags or shortcodes, try http://slidervilla.com/ I've purchased several from there and love 'em! The designer is continuously improving on them, and she offers great support too.

    If you go the tabbed content route, you can display your products using shortcodes with no problem, and style the display through your theme's stylesheet. The content under the "Newest" and "Most Popular" tabs on the my frontpage is rendered with Marketpress global shortcodes.

    Have fun! If you need help with specifics, give me a shout!

    congrats on the lifetime membership

    Thanks! :slight_smile:

  • Fondeli
    • The Bug Hunter

    Wow @pcwriter I hadn't even thought of creating a front page.

    So I have, only problem was the product grid didn't look quite right, so I had a play around with the css. The product price gave me a bit of a headache, as it made the grid all loopy, but I thought I had it sorted with visibility. I hid the mp_product_price, and showed the mp_current_price then gave it a negative left margin, but this changed it on all category pages, so in the end, just removed the price. I can't seem to find how the word "price" is not shown on the Gridmarket product pages!

    I used the recent post slider: http://wordpress.org/extend/plugins/recent-posts-slider/

    It was fun! :slight_smile: Have a look, let me know what you think http://fondelifair.com

    Thanks a million for the advice!!

  • josh
    • Site Builder, Child of Zeus

    @Patrick Cohen

    Nice tutorial! Thanks for taking your time and helping us out!

    First question, is there a new link for the demo/example? The one you gave isn't working anymore, and I'm not sure how this is suppose to look in the end.

    Second, I am trying to implement a rating/review system for my MU + Marketpress set up. But I don't want any user to be able to review a product or store, but instead only people that have bought from the store. Ideally they could only review once per item bought.

    Is your tut here, what I need? Anything that I should do different than you described above?

    Thanks!!

  • Patrick
    • Support Monkey

    Hiya @josh

    Back from Christmas holiday. I hope you had a great holiday too!

    I don't want any user to be able to review a product or store, but instead only people that have bought from the store. Ideally they could only review once per item bought. Is your tut here, what I need?

    No, this tutorial wouldn't work for what you want to set up. This is a simple way for sub-site admins to create a page on your main site where users can leave reviews for their site/store.

    It wouldn't work for products, much less restrict the ability to leave reviews to only those users who have purchased a product.

    You can, however, allow comments on products with a plugin like this one:
    http://wordpress.org/plugins/wpmu-marketpress-allow-comments-addon/

    Or with a 3rd-party theme specifically designed for MarketPress like this one:
    http://www.marketpressthemes.com/pro-premium-theme-for-marketpress/

    That's going to require more in-depth coding than I can actually provide too. I'm a wiz at copy/paste, but not so hot when it comes to writing custom code. :slight_smile:

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.