Skip Navigation

[Resolved] Adding unique widget script to each custom post

This thread is resolved. Here is a description of the problem and solution.

Problem: I would like to display a JavaScript widget on the single post page for my custom post type. Each post will have a unique script tag, so I would like to store that in a custom field. I have created a post template with Elementor for this custom post type, and I would like to inject the script from the custom field into the single post template.

Solution: You can use a custom shortcode to generate the script tag, then place that custom shortcode in your Elementor template.

function ts_show_widget( $atts ) {
  global $post;
  $field_slug = 'unique-string'; // replace this with the slug of your custom field
  $atts = shortcode_atts([
    'postid' => isset($post->ID) ? $post->ID : 0
  ], $atts);
  $field = types_render_field($field_slug, array( 'item'=>$atts['postid'], 'output'=>'raw'));
  $script = "<script>console.log('Unique string: " . $field . "');</script>"; // update your script here
  return $script;
}
add_shortcode( 'ts-show-widget', 'ts_show_widget' );

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

This topic contains 8 replies, has 2 voices.

Last updated by patrickM-3 2 years, 5 months ago.

Assigned support staff: Christian Cox.

Author
Posts
#1198037

Tell us what you are trying to do?

Website is for a chain of multiple dentist offices. One custom post type is "Locations" and another is "dentists". There is a many-to-many relationship between Locations and Dentists. I've created a single template for displaying locations following the directions for Elementor Pro and I have nested a view showing the dentists at that location. All working fine.

The client uses an SEO company to display ratings and allow users to rate and review each office location. The ratings company provides a JavaScript widget so that site visitors can see reviews for a location and add their own ratings and reviews. The widget code is the same except for an included string that is unique for each location.

I need a way to add the unique widget script to the locations single template using Elementor Pro, so that the correct javascript for each location is loaded and displays on the single location template.

#1198249

Christian Cox
Supporter

Languages: English (English )

Timezone: America/New_York (GMT-04:00)

Hi, there's not a built-in way to create dynamic JavaScript code like this. You can add a script tag in an HTML element in your Elementor template, but it won't render Views shortcodes. That means it's not possible to make it dynamic (based on where the template is shown). I think your best option here is to use a Types custom field to store the unique string for each Location post. Then create a custom shortcode that builds the script tag using the value of that custom field, and insert that shortcode in a Text element in your Elementor template. Example PHP code in functions.php:

function ts_show_widget( $atts ) {
  global $post;
  $field_slug = 'unique-string'; // replace this with the slug of your custom field
  $atts = shortcode_atts([
    'postid' => isset($post->ID) ? $post->ID : 0
  ], $atts);
  $field = types_render_field($field_slug, array( 'item'=>$atts['postid'], 'output'=>'raw'));
  $script = "<script>console.log('Unique string: " . $field . "');</script>"; // update your script here
  return $script;
}
add_shortcode( 'ts-show-widget', 'ts_show_widget' );

Then in your template:

[ts-show-widget]
#1198828
Screen Shot 2019-02-11 at 12.58.45 PM.png

Thank You Christian. I've added the following script to the child theme functions.php file:

function location_widget( $atts ) {
  global $post;
  $field_slug = 'lighthouse-widget-code'; //  slug of Toolset custom field
  $atts = shortcode_atts([
    'postid' => isset($post->ID) ? $post->ID : 0
  ], $atts);
  $field = types_render_field($field_slug, array( 'item'=>$atts['postid'], 'output'=>'raw'));
  $script = "<script>" . $field . "</script>";
  return $script;
}
add_shortcode( 'location-widget', 'location_widget' );

I've added the following to an Elementor Pro text editor element:

<div id="review-widget-container" style="width: 220px;"></div>
[location-widget]

As you can see on this page: hidden link the widget is rendering the content twice. The list of reviews is duplicated and, because of CSS, the header is not repeated. If you inspect the source where this widget is, you will see that the javascript is appearing twice.

Any idea how I did this?

#1198934

I should also point out that I'm trying to insert the widget into the single template for the custom post type Locations, which was created using Types.

#1198944

Christian Cox
Supporter

Languages: English (English )

Timezone: America/New_York (GMT-04:00)

Screen Shot 2019-02-11 at 5.33.04 PM.png

It looks like the JavaScript code is included in this page twice. If you open the browser console and search for "review-widget-container" you can see three occurrences. There should only be two - once in the container div and another in the script itself. The second instance is included in a section with a comment about OceanWP JS, so I assume this means there is a theme option that allows you to insert arbitrary script code, or it's been added to a child theme's functions.php file. Remove it from there if you want to include it in a custom field instead.

#1199375

The unique widget javascript in stored in a custom field for each Location. The slug for that field is "lighthouse-widget-code" and it contains similar strings to this:

(function(w, d){w._rab_review_q = w._rab_review_q || []; w._rab_review_q.push({id: 'c322c7a93a518b096e9ec1d77c5e52ab', reviewDivId: 'review-widget-container', template: 'light', seoFriendlyName: 'rlj-dental-appleton-appleton-wi'}); var el = d.createElement("script"); el.async=true; el.src="//s3.amazonaws.com/cdn.rateabiz.com/reviews/loader.js"; el.type="text/javascript"; var s0 = d.getElementsByTagName("script")[0]; s0.parentNode.insertBefore(el, s0);})(window, document);

The child theme functions.php contains only the code for creating the [lighthouse-widget] according to your instructions.

In the single template for Locations I have added a div where the widget is supposed to be injected and the shortcode:

<div id="review-widget-container" style="width: 220px;"></div>
[location-widget]

There are no other places where either the javascript or the widget are included. I have hacked the CSS to reduce the height of the rendered widget to hide the duplicate review list, but the code is being added to the page twice. Any ideas?

#1199396

Christian Cox
Supporter

Languages: English (English )

Timezone: America/New_York (GMT-04:00)

May I log in and see how this is set up in wp-admin? I must be missing something.

#1199485

Christian Cox
Supporter

Languages: English (English )

Timezone: America/New_York (GMT-04:00)

There are no other places where either the javascript or the widget are included.
Go to Appearance > Customize > Custom CSS / JS and scroll down to the bottom. You will see custom JavaScript included here. It looks like this is the duplicate code. Maybe someone else put it here, but you should be able to remove it.

#1199545

Wow! My client did that for me & I didn't think to check there. Christian, you're a genius!

Many thanks! My problem is solved and this simple solution will work for any similar situation where some custom Javascript needs to be injected on a post by post basis.