Changeset 2042059
- Timestamp:
- 03/01/2019 11:28:04 AM (7 years ago)
- Location:
- storespot
- Files:
-
- 2 added
- 18 edited
- 1 copied
-
tags/1.1.0 (copied) (copied from storespot/trunk)
-
tags/1.1.0/admin/class-storespot-api.php (modified) (3 diffs)
-
tags/1.1.0/admin/class-storespot-async.php (added)
-
tags/1.1.0/admin/class-storespot-productfeed.php (modified) (14 diffs)
-
tags/1.1.0/includes/class-storespot-activator.php (modified) (1 diff)
-
tags/1.1.0/includes/class-storespot-deactivator.php (modified) (1 diff)
-
tags/1.1.0/includes/class-storespot.php (modified) (6 diffs)
-
tags/1.1.0/public/class-storespot-events.php (modified) (11 diffs)
-
tags/1.1.0/public/class-storespot-facebook-pixel.php (modified) (1 diff)
-
tags/1.1.0/readme.txt (modified) (2 diffs)
-
tags/1.1.0/storespot.php (modified) (2 diffs)
-
trunk/admin/class-storespot-api.php (modified) (3 diffs)
-
trunk/admin/class-storespot-async.php (added)
-
trunk/admin/class-storespot-productfeed.php (modified) (14 diffs)
-
trunk/includes/class-storespot-activator.php (modified) (1 diff)
-
trunk/includes/class-storespot-deactivator.php (modified) (1 diff)
-
trunk/includes/class-storespot.php (modified) (6 diffs)
-
trunk/public/class-storespot-events.php (modified) (11 diffs)
-
trunk/public/class-storespot-facebook-pixel.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/storespot.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
storespot/tags/1.1.0/admin/class-storespot-api.php
r1969706 r2042059 16 16 'permission_callback' => array( $this, 'get_settings_permission_check' ), 17 17 )); 18 19 register_rest_route( $this->namespace, '/storespot/feed/', array( 20 'methods' => WP_REST_SERVER::READABLE, 21 'callback' => array( $this, 'update_storespot_feed' ), 22 'permission_callback' => array( $this, 'get_settings_permission_check' ), 23 ) ); 18 24 } 19 25 … … 30 36 } 31 37 32 public function update_storespot_settings($request) {33 $settings = $request['settings'];34 update_option( 'storespot_settings', $settings );35 if ( ! wp_next_scheduled( 'stsp_product_feed_update' ) ) {36 wp_schedule_event( time(), 'hourly', 'stsp_product_feed_update' );37 }38 39 $data = array( 'updated' => true, 'settings' => get_option( 'storespot_settings' ) );40 $response = rest_ensure_response($data);41 $response->set_status(200);42 43 return $response;44 }45 46 38 public function get_settings_permission_check() { 47 39 if ( !wc_rest_check_user_permissions('read') ) { … … 56 48 } 57 49 58 public function get_storespot_settings($request) { 59 if ( wp_next_scheduled( 'stsp_product_feed_update' ) ) { 60 $cronjob = date( 61 'Y-m-d h:i:s', 62 wp_next_scheduled( 'stsp_product_feed_update' ) 63 ); 64 } else { 65 $cronjob = false; 50 public function update_storespot_settings($request) { 51 $new_settings = $request['settings']; 52 $current_settings = get_option( 'storespot_settings' ); 53 54 foreach( $new_settings as $key => $value ) { 55 $current_settings[$key] = $value; 66 56 } 67 57 68 if ( ! function_exists( 'get_plugins' ) ) { 69 require_once ABSPATH . 'wp-admin/includes/plugin.php'; 70 } 58 $updated = update_option( 'storespot_settings', $current_settings ); 59 $data = array( 'updated' => $updated ); 71 60 72 $plugins = get_plugins(); 73 $plugins_view = array(); 74 foreach( $plugins as $plugin ) { 75 array_push($plugins_view, array( 76 'name' => $plugin['Name'], 77 'version' => $plugin['Version'], 78 )); 79 } 61 $response = rest_ensure_response($data); 62 $response->set_status(200); 63 return $response; 64 } 80 65 66 public function get_storespot_settings($request) { 81 67 $data = array( 82 'cronjob' => $cronjob, 83 'plugin_version' => STORESPOT_VERSION, 84 'settings' => get_option( ' storespot_settings' ), 85 'wp_version' => get_bloginfo( 'version' ), 86 'wc_version' => get_option( 'woocommerce_version' ), 87 'plugins' => $plugins_view, 68 'settings' => get_option( 'storespot_settings' ), 69 'feed' => get_option( 'storespot_feed' ), 70 'stsp_version' => STORESPOT_VERSION, 71 'wp_version' => get_bloginfo( 'version' ), 72 'wc_version' => get_option( 'woocommerce_version' ), 88 73 ); 89 74 90 75 $response = rest_ensure_response($data); 91 76 $response->set_status(200); 77 return $response; 78 } 92 79 80 public function update_storespot_feed() { 81 do_action('stsp_call_async_feed_update'); 82 $response = rest_ensure_response(array( 'received' => true )); 83 $response->set_status(200); 93 84 return $response; 94 85 } -
storespot/tags/1.1.0/admin/class-storespot-productfeed.php
r1977618 r2042059 7 7 protected $feed_items = null; 8 8 protected $factory = null; 9 protected $url = null; 9 protected $url = null; 10 protected $writer = null; 10 11 protected $chunk_size = 0; 11 protected $offset = 0;12 protected $offset = 0; 12 13 protected $settings = array(); 13 protected $store = array();14 protected $store = array(); 14 15 15 16 public function __construct() { 16 17 17 18 $this->chunk_size = $this->stsp_get_chunk_size(); 18 $this->settings = $this->stsp_get_settings();19 $this->store = array(19 $this->settings = $this->stsp_get_settings(); 20 $this->store = array( 20 21 'name' => get_bloginfo( 'name' ), 21 22 'url' => get_site_url(), … … 32 33 $upload_dir = $this->upload_directory(); 33 34 $dir_path = $upload_dir['dir_path']; 34 $path = $upload_dir['file_path'];35 $path = $upload_dir['file_path']; 35 36 $this->url = $upload_dir['file_url']; 36 37 37 if ( file_exists( $dir_path ) ) { 38 $fp = fopen( $path, 'w' ); 39 fwrite( $fp, $this->stsp_create_feed() ); 40 fclose( $fp ); 41 } 42 38 $tmp = $path.".tmp"; 39 if (file_exists( $tmp )) { 40 unlink( $tmp ); 41 } 42 43 if ( $this->settings['feed'] === true && file_exists( $dir_path ) ) { 44 $this->stsp_create_feed($tmp); 45 } 46 47 rename($path . ".tmp", $path); 43 48 return $this->url; 44 49 } … … 47 52 48 53 $wp_upload_dir = wp_upload_dir(); 49 $basedir = $wp_upload_dir['basedir'];50 $baseurl = $wp_upload_dir['baseurl'];54 $basedir = $wp_upload_dir['basedir']; 55 $baseurl = $wp_upload_dir['baseurl']; 51 56 $storespot_dir = $basedir . '/storespot/'; 52 57 $storespot_url = $baseurl . '/storespot/'; … … 73 78 74 79 $settings = array( 75 'pixel_id' => null, 76 'category' => null, 80 'category' => null, 81 'feed' => false, 82 'start_memory' => null, 83 'end_memory' => null, 77 84 ); 78 85 $config = get_option( 'storespot_settings', array() ); … … 81 88 $settings['category'] = $config['product_category']; 82 89 } 83 if( array_key_exists( ' pixel_id', $config ) ) {84 $settings[' pixel_id'] = $config['pixel_id'];90 if( array_key_exists( 'feed_enabled', $config ) ) { 91 $settings['feed'] = $config['feed_enabled']; 85 92 } 86 93 } … … 107 114 if ( function_exists( 'wc_get_products' ) ) { 108 115 $args = array( 109 'status' => array( 'publish' ), 110 'type' => array( 'simple', 'variable', 'bundle', 'composite' ), 111 'offset' => $this->offset, 112 'limit' => $this->chunk_size, 116 'status' => array( 'publish' ), 117 'offset' => $this->offset, 118 'limit' => $this->chunk_size, 113 119 ); 114 120 return array( 'wc_get_products', $args ); 115 121 } else { 116 122 $args = array( 117 'post_type' => 'product',118 'offset' => $this->offset,119 'numberposts' => $this->chunk_size,123 'post_type' => 'product', 124 'offset' => $this->offset, 125 'numberposts' => $this->chunk_size, 120 126 ); 121 127 return array( 'get_posts', $args ); … … 124 130 } 125 131 126 private function stsp_create_feed() { 127 128 // Log every feed start 129 error_log( 130 "\n" . date('Y-m-d h:i:s'). " :: starting feed write", 131 3, 132 $this->log_file() 133 ); 134 135 // Make header first 136 $output = ""; 137 $output .= $this->stsp_render_header(); 138 139 // Render entries 132 private function stsp_create_feed($file) { 133 error_log("\n".date('Y-m-d h:i:s')." :: starting feed write",3,$this->log_file()); 134 135 $this->settings['start_memory'] = memory_get_peak_usage(); 136 $this->writer = new XMLWriter(); 137 $this->writer->openMemory(); 138 $this->writer->startDocument('1.0', 'UTF-8'); 139 $this->stsp_render_header(); 140 140 141 $this->factory = new WC_Product_Factory(); 141 142 list($query, $args) = $this->stsp_create_query(); … … 144 145 $products = $query( $args ); 145 146 while ( count( $products ) ) { 146 147 147 // Process products in query 148 148 foreach ( $products as $product ) { 149 $output .= $this->stsp_render_entry( $product ); 150 } 151 152 // Flush internal cache for memory optimization 153 if ( ! wp_using_ext_object_cache() ) { 154 wp_cache_flush(); 149 $this->stsp_render_entry( $product ); 155 150 } 156 151 … … 158 153 $args['offset'] += $this->chunk_size; 159 154 $products = $query( $args ); 160 } 161 162 // Make footer 163 $output .= $this->stsp_render_footer(); 164 165 // Log every feed end 166 error_log( 167 "\n" . date('Y-m-d h:i:s'). " :: completed feed write", 168 3, 169 $this->log_file() 170 ); 171 172 return $output; 155 156 // Write & flush 157 file_put_contents($file, $this->writer->flush(true), FILE_APPEND); 158 } 159 160 $this->settings['end_memory'] = memory_get_peak_usage(); 161 162 $this->stsp_render_footer(); 163 file_put_contents($file, $this->writer->flush(true), FILE_APPEND); 164 error_log("\n".date('Y-m-d h:i:s')." :: completed feed write",3,$this->log_file()); 173 165 } 174 166 175 167 private function stsp_render_header() { 176 177 $header = ""; 178 $header .= "<?xml version='1.0' encoding='UTF-8' ?>\n"; 179 $header .= "<feed xmlns='http://www.w3.org/2005/Atom' xmlns:g='http://base.google.com/ns/1.0'>\n"; 180 $header .= " <title><![CDATA[" . $this->store['name'] . " - Facebook Product Feed]]></title>\n"; 181 $header .= " <link rel='self' href='" . $this->url . "'/>\n"; 182 return $header; 183 168 // Start feed 169 $this->writer->startElement('feed'); 170 $this->writer->writeAttribute('xmlns', 'http://www.w3.org/2005/Atom'); 171 $this->writer->writeAttribute('xmlns:g', 'http://base.google.com/ns/1.0'); 172 173 // Add title 174 $this->writer->startElement('title'); 175 $this->writer->writeCData($this->store['name'] . " - Facebook Product Feed"); 176 $this->writer->endElement(); 177 178 // Add link 179 $this->writer->startElement('link'); 180 $this->writer->writeAttribute('rel', 'self'); 181 $this->writer->writeAttribute('href', $this->url); 182 $this->writer->endElement(); 184 183 } 185 184 186 185 private function stsp_render_footer() { 187 188 return '</feed>'; 186 $this->writer->endElement(); 187 $this->writer->writeComment('Created: ' . date('Y-m-d H:i:s', time())); 188 $this->writer->writeComment('Start memory: ' . round( $this->settings['start_memory'] / 1024 / 1024, 2 ) . ' MB'); 189 $this->writer->writeComment('End memory: ' . round( $this->settings['end_memory'] / 1024 / 1024, 2 ) . ' MB'); 189 190 190 191 } … … 219 220 private function stsp_variable_product( $product ) { 220 221 $variations = $product->get_available_variations(); 221 $output = '';222 222 foreach ( $variations as $variation ) { 223 223 $variation_id = $variation['variation_id']; 224 224 $variation = $this->factory->get_product( $variation_id ); 225 $ output .= $this->stsp_render_product( $variation, $product );226 } 227 return $output;225 $this->stsp_render_product( $variation, $product ); 226 } 227 return; 228 228 } 229 229 230 230 private function stsp_render_product( $product, $parent=null ) { 231 231 232 $image_link = $this->render_image_link( $product );232 $image_link = $this->render_image_link( $product ); 233 233 if( ! $image_link ) { 234 234 if( ! $parent ) … … 243 243 $product_id = $product->get_id(); 244 244 $product_sku = $product->get_sku(); 245 $feed_id = $product_sku ? 246 $product_sku . '_' . $product_id : 247 'wc_post_id_' . $product_id; 248 249 $group_id = $parent ? $parent->get_id() : null; 250 $product_name = $product->get_name(); 251 $product_price= $product->get_price() . ' ' . $this->settings['currency']; 245 $feed_id = 'stsp_' . $product_id; 246 247 $group_id = $parent ? 'stsp_' . $parent->get_id() : null; 248 $product_name = ucwords(strtolower($product->get_name())); 249 $product_price = $product->get_price() . ' ' . $this->settings['currency']; 252 250 $description = $this->render_description( $product ); 253 $availability = $this->render_availability( $product );251 $availability = $this->render_availability( $product ); 254 252 $condition = 'new'; 255 253 $image_link = $this->render_image_link( $product ); 256 254 $additional = $this->render_additional_images( $product ); 257 $brand = $this->render_brand( $product);258 $link = $this->render_product_link( $product );255 $brand = $this->render_brand( $product_id ); 256 $link = $this->render_product_link( $product ); 259 257 $sale_price = ( $product->is_on_sale() && $product->get_sale_price() ) ? 260 $product->get_sale_price() . ' ' . $this->settings['currency'] :261 null;258 $product->get_sale_price() . ' ' . $this->settings['currency'] : 259 null; 262 260 $sale_from = $product->get_date_on_sale_from(); 263 $sale_to = $product->get_date_on_sale_to();261 $sale_to = $product->get_date_on_sale_to(); 264 262 265 263 // Fixes for product variations … … 282 280 283 281 // Render output 284 $output = ""; 285 $output .= " <entry>\n"; 286 $output .= " <g:id>" . $feed_id . "</g:id>\n"; 287 $output .= " <g:title><![CDATA[" . $title . "]]></g:title>\n"; 288 $output .= " <g:description><![CDATA[" . $description . "]]></g:description>\n"; 289 $output .= " <g:availability>" . $availability . "</g:availability>\n"; 290 $output .= " <g:condition>" . $condition . "</g:condition>\n"; 291 $output .= " <g:link>" . $link . "</g:link>\n"; 292 $output .= " <g:price>" . $product_price . "</g:price>\n"; 293 $output .= " <g:brand><![CDATA[" . $brand . "]]></g:brand>\n"; 294 $output .= " <g:image_link><![CDATA[" . $image_link . "]]></g:image_link>\n"; 282 $this->writer->startElement('entry'); 283 $this->writer->writeElement('g:id', $feed_id); 284 $this->writer->startElement('g:title');$this->writer->writeCData($title);$this->writer->endElement(); 285 $this->writer->startElement('g:description');$this->writer->writeCData($description);$this->writer->endElement(); 286 $this->writer->writeElement('g:availability', $availability); 287 $this->writer->writeElement('g:condition', $condition); 288 $this->writer->writeElement('g:link', $link); 289 $this->writer->writeElement('g:price', $product_price); 290 $this->writer->startElement('g:brand');$this->writer->writeCData($brand);$this->writer->endElement(); 291 $this->writer->startElement('g:image_link');$this->writer->writeCData($image_link);$this->writer->endElement(); 295 292 296 293 if( $group_id ) { 297 $ output .= " <g:item_group_id>" . $group_id . "</g:item_group_id>\n";298 } 299 300 if( $additional _image_link) {301 $ output .= " <g:additional_image_link><![CDATA[" . $additional_image_link . "]]></g:additional_image_link>\n";294 $this->writer->writeElement('g:item_group_id', $group_id); 295 } 296 297 if( $additional ) { 298 $this->writer->startElement('g:additional_image_link');$this->writer->writeCData($additional);$this->writer->endElement(); 302 299 } 303 300 304 301 if( $sale_price ) { 305 $ output .= " <g:sale_price><![CDATA[" . $sale_price . "]]></g:sale_price>\n";302 $this->writer->writeElement('g:sale_price', $sale_price); 306 303 } 307 304 308 305 if( $sale_from ) { 309 $ output .= " <g:sale_price_start_date><![CDATA[" . $sale_from . "]]></g:sale_price_start_date>\n";306 $this->writer->startElement('g:sale_price_start_date');$this->writer->writeCData($sale_from);$this->writer->endElement(); 310 307 } 311 308 312 309 if( $sale_to ) { 313 $ output .= " <g:sale_price_end_date><![CDATA[" . $sale_to . "]]></g:sale_price_end_date>\n";310 $this->writer->startElement('g:sale_price_end_date');$this->writer->writeCData($sale_to);$this->writer->endElement(); 314 311 } 315 312 316 313 if( $this->settings['category'] ) { 317 $output .= " <g:google_product_category><![CDATA[" . $this->settings['category'] . "]]></g:google_product_category>\n"; 318 } 319 320 $output .= " </entry>\n"; 321 322 return $output; 314 $this->writer->writeElement('g:google_product_category', $this->settings['category']); 315 } 316 317 $this->writer->endElement(); 318 return; 323 319 } 324 320 … … 370 366 private function render_additional_images( $product ) { 371 367 $gallery_image_ids = $product->get_gallery_image_ids(); 368 $additional_image_link = null; 372 369 if ( $gallery_image_ids ) { 373 370 $i = 0; … … 406 403 } 407 404 408 private function render_brand( $product ) {405 private function render_brand( $product_id ) { 409 406 $term_names = wp_get_post_terms( 410 407 $product_id, 'brand', array('orderby'=>'name', 'fields' => 'names') -
storespot/tags/1.1.0/includes/class-storespot-activator.php
r1957373 r2042059 7 7 $stsp_settings = get_option('storespot_settings'); 8 8 9 if( $stsp_settings && array_key_exists( 'product_feed', $stsp_settings )) { 10 $feed = $stsp_settings['product_feed']; 11 if ( $feed && !wp_next_scheduled( 'stsp_product_feed_update' ) ) { 12 wp_schedule_event( time(), 'hourly', 'stsp_product_feed_update' ); 13 } 14 } else { 9 if( !$stsp_settings ) { 15 10 $options = [ 16 'pixel_id' => '', 17 'product_feed' => 'no', 18 'product_category' => '' 11 'pixel_id' => null, 12 'pixel_enabled' => false, 13 'feed_enabled' => false, 14 'product_category' => 0, 19 15 ]; 20 21 16 add_option( 'storespot_settings', $options ); 17 add_option( 'storespot_feed', null ); 22 18 } 23 19 -
storespot/tags/1.1.0/includes/class-storespot-deactivator.php
r1977618 r2042059 2 2 class StoreSpot_Deactivator { 3 3 public static function deactivate() { 4 wp_clear_scheduled_hook( 'stsp_product_feed_update' );5 4 delete_option( 'storespot_settings' ); 5 delete_option( 'storespot_feed' ); 6 6 } 7 7 } -
storespot/tags/1.1.0/includes/class-storespot.php
r1977618 r2042059 22 22 $this->version = STORESPOT_VERSION; 23 23 } else { 24 $this->version = ' 1.0.0';24 $this->version = '0.0.0'; 25 25 } 26 26 $this->plugin_name = 'storespot'; … … 46 46 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-messages.php'; 47 47 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-api.php'; 48 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-async.php'; 48 49 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-storespot-events.php'; 49 50 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-storespot-facebook-pixel.php'; … … 55 56 ! class_exists( 'StoreSpot_API' ) || 56 57 ! class_exists( 'StoreSpot_Events' ) || 57 ! class_exists( 'StoreSpot_Facebook_Pixel' ) 58 ! class_exists( 'StoreSpot_Facebook_Pixel' ) || 59 ! class_exists( 'StoreSpot_Async' ) 58 60 ) { 59 61 return false; … … 65 67 66 68 private function define_admin_hooks() { 67 $product_feed = new StoreSpot_Product_Feed();68 69 $admin_message = new StoreSpot_Messages(); 69 $this->loader->add_action( 'stsp_product_feed_update', $product_feed, 'write_product_feed' ); 70 $async_request = new StoreSpot_Async(); 71 $products_feed = new StoreSpot_Product_Feed(); 70 72 $this->loader->add_action( 'admin_notices', $admin_message, 'activation_notice' ); 73 $this->loader->add_action( 'wp_ajax_' . $async_request->get_ajax_action(), $async_request, 'execute' ); 74 $this->loader->add_action( 'wp_ajax_nopriv_' . $async_request->get_ajax_action(), $async_request, 'execute' ); 75 $this->loader->add_action( 'stsp_call_async_feed_update', $async_request, 'call' ); 76 $this->loader->add_action( $async_request->get_feed_action(), $products_feed, 'write_product_feed' ); 71 77 } 72 78 … … 74 80 $plugin_public = new StoreSpot_Events( $this->get_plugin_name(), $this->get_version() ); 75 81 $pixel_id = $plugin_public->facebook_pixel->get_pixel_id(); 76 if( $pixel_id && ! $this->fb_integration_installed( $pixel_id )) {82 if( $pixel_id ) { 77 83 $this->loader->add_action( 'wp_head', $plugin_public, 'render_facebook_pixel' ); 78 $this->loader->add_action( 'wp_ head', $plugin_public, 'render_facebook_pixel_noscript' );84 $this->loader->add_action( 'wp_footer', $plugin_public, 'render_facebook_pixel_noscript' ); 79 85 $this->loader->add_action( 'woocommerce_after_single_product', $plugin_public, 'render_product_view_event'); 80 86 $this->loader->add_action( 'woocommerce_after_shop_loop', $plugin_public, 'render_category_view_event'); … … 84 90 $this->loader->add_action( 'woocommerce_after_checkout_form', $plugin_public, 'render_initiate_checkout_event' ); 85 91 $this->loader->add_action( 'woocommerce_thankyou', $plugin_public, 'render_purchase_event' ); 92 $this->loader->add_action( 'woocommerce_payment_complete', $plugin_public, 'render_purchase_event' ); 86 93 $this->loader->add_action( 'wp_footer', $plugin_public, 'custom_jquery_add_to_cart_script' ); 87 $this->loader->add_action( 'wc_ajax_ render_add_to_cart_event', $plugin_public, 'render_ajax_add_to_cart_event' );94 $this->loader->add_action( 'wc_ajax_stsp_add_to_cart_event', $plugin_public, 'render_ajax_add_to_cart_event' ); 88 95 } 89 96 } 90 97 91 private function fb_integration_installed($pixel_id) {92 $fb_option = get_option('facebook_config');93 $fb_integration_option_set = false;94 if ( $fb_option && array_key_exists( 'pixel_id', $fb_option ) ) {95 if ( $fb_option['pixel_id'] == $pixel_id) {96 $fb_integration_option_set = true;97 }98 }99 include_once( ABSPATH . 'wp-admin/includes/plugin.php' );100 $fb_integration_activated = class_exists('WC_Facebookcommerce');101 return $fb_integration_activated && $fb_integration_option_set;102 }103 104 98 private function define_api_hooks() { 105 $api = new StoreSpot_API();106 $this->loader->add_action( 'rest_api_init', $api, 'storespot_api_route');99 $api = new StoreSpot_API(); 100 $this->loader->add_action( 'rest_api_init', $api, 'storespot_api_route'); 107 101 } 108 102 -
storespot/tags/1.1.0/public/class-storespot-events.php
r1982419 r2042059 18 18 public function get_facebook_content_id($product) { 19 19 $product_id = $product->get_id(); 20 $product_sku = $product->get_sku(); 21 $sku_id = $product_sku . '_' . $product_id; 22 $other_id = 'wc_post_id_' . $product_id; 23 24 $ids = array($other_id, $product_id); 25 if ( $product_sku ) { 26 $ids[] = $sku_id; 27 $ids[] = $product_sku; 28 } 29 30 return $ids; 20 return 'stsp_' . $product->get_id(); 31 21 } 32 22 … … 34 24 global $post; 35 25 $product = wc_get_product($post->ID); 26 $content_type = 'product'; 36 27 37 28 if ( $product ) { 29 if( $product->get_type() == 'variable' ) { 30 $content_type = 'product_group'; 31 } 38 32 $params = array(); 33 $params['content_ids'] = json_encode( [$this->get_facebook_content_id( $product )] ); 34 $params['content_type'] = $content_type; 35 $params['content_name'] = $product->get_title(); 36 $params['currency'] = get_woocommerce_currency(); 39 37 $params['value'] = $product->get_price(); 40 $params['content_name'] = $product->get_title();41 $params['content_type'] = ($product->get_type() == 'variable' ? 'product_group' : 'product');42 $params['currency'] = get_woocommerce_currency();43 $params['content_ids'] = json_encode( $this->get_facebook_content_id( $product ) );44 38 45 39 $this->facebook_pixel->event_code( 'ViewContent', $params ); … … 53 47 54 48 $products = array_values(array_map(function($item) { 55 return wc_get_product($item->ID);56 }, $wp_query->posts));49 return wc_get_product($item->ID); 50 }, $wp_query->posts)); 57 51 58 52 $content_type = 'product'; … … 60 54 foreach ($products as $product) { 61 55 if (!$product) { continue; } 62 $product_ids = array_merge( 63 $product_ids, 64 $this->get_facebook_content_id($product) 65 ); 66 if ($product->get_type() == 'variable') { 67 $content_type = 'product_group'; 68 } 69 } 70 71 $category_path = wp_get_post_terms( get_the_ID(), 'product_cat' ); 56 if ( $product->get_type() == 'variable' ) { continue; } 57 $product_ids[] = $this->get_facebook_content_id($product); 58 } 59 60 $category_path = wp_get_post_terms( get_the_ID(), 'product_cat' ); 72 61 $content_category = array_values( array_map( function($item) { 73 62 return $item->name; … … 81 70 82 71 $params = array( 83 'content_name' => json_encode($categories['name']),72 'content_name' => json_encode($categories['name']), 84 73 'content_category' => json_encode($categories['categories']), 85 'content_ids' => json_encode(array_slice($product_ids, 0, 10)),86 'content_type' => $content_type74 'content_ids' => json_encode($product_ids), 75 'content_type' => $content_type 87 76 ); 88 77 … … 112 101 $product_ids = array(); 113 102 foreach ( $products as $item ) { 114 $product_ids = array_merge( 115 $product_ids, 116 $this->get_facebook_content_id( $item['data'] ) 117 ); 103 $product_ids[] = $this->get_facebook_content_id( $item['data'] ); 118 104 } 119 105 … … 134 120 135 121 public function render_ajax_add_to_cart_event() { 122 136 123 global $woocommerce; 137 124 $products = $woocommerce->cart->get_cart(); 125 126 ob_start(); 127 138 128 $product_ids = array(); 139 129 foreach ( $products as $item ) { 140 $product_ids = array_merge( 141 $product_ids, 142 $this->get_facebook_content_id( $item['data'] ) 143 ); 144 } 130 $product_ids[] = $this->get_facebook_content_id( $item['data'] ); 131 } 132 145 133 $params = array(); 146 134 $params['content_ids'] = json_encode( $product_ids ); … … 149 137 $params['currency'] = get_woocommerce_currency(); 150 138 151 $code = $this->facebook_pixel->ajax_event_code( 'AddToCart', $params ); 152 wp_send_json($code); 139 echo $this->facebook_pixel->ajax_event_code( 'AddToCart', $params ); 140 141 $pixel = ob_get_clean(); 142 wp_send_json($pixel); 153 143 } 154 144 … … 162 152 $product_ids = array(); 163 153 foreach ( $products as $item ) { 164 $product_ids = array_merge( 165 $product_ids, 166 $this->get_facebook_content_id( $item['data'] ) 167 ); 154 $product_id[] = $this->get_facebook_content_id( $item['data'] ); 168 155 } 169 156 … … 184 171 185 172 $order = wc_get_order( $order_id ); 173 $content_type = 'product'; 186 174 $product_ids = array(); 187 175 foreach ( $order->get_items() as $item ) { 188 176 $product = $item->get_product(); 189 $product_ids = array_merge(190 $product_ids, 191 $this->get_facebook_content_id( $product ) 192 );193 } 194 195 $params = array(); 196 $params['content_ids'] = json_encode( $product_ids ); 197 $params['content_type'] = 'product';177 $product_ids[] = $this->get_facebook_content_id( $product ); 178 if( $product->get_type() == 'variable' ) { 179 $content_type = 'product_group'; 180 } 181 } 182 183 $params = array(); 184 $params['content_ids'] = json_encode( $product_ids ); 185 $params['content_type'] = $content_type; 198 186 $params['value'] = $order->get_total(); 199 187 $params['currency'] = get_woocommerce_currency(); … … 203 191 204 192 public function custom_jquery_add_to_cart_script(){ 205 if ( is_shop() || is_product_category() || is_product_tag() ): 206 ?> 207 <script type="text/javascript"> 208 (function($){ 209 $( document.body ).on( 'added_to_cart', function(){ 210 $.get('?wc-ajax=render_add_to_cart_event', function(script) { 211 console.log(script); 212 $('head').append(script); 213 }); 214 }); 215 })(jQuery); 216 </script> 217 <?php 218 endif; 193 if ( is_front_page() || is_shop() || is_product_category() || is_product_tag() ) { 194 195 echo " 196 <!-- StoreSpot Facebook Listener Begin --> 197 <script type='text/javascript'> 198 document.addEventListener('DOMContentLoaded', function() { 199 jQuery && jQuery(function($){ 200 $('body').on('added_to_cart', function(event) { 201 // Ajax action. 202 $.get('?wc-ajax=stsp_add_to_cart_event', function(data) { 203 $('head').append(data); 204 }); 205 }); 206 }); 207 }, false); 208 </script> 209 <!-- StoreSpot Facebook Listener End --> 210 "; 211 212 } 219 213 } 220 214 } -
storespot/tags/1.1.0/public/class-storespot-facebook-pixel.php
r1969706 r2042059 40 40 public function get_pixel_id() { 41 41 $stsp_settings = get_option( 'storespot_settings' ); 42 if( $stsp_settings && array_key_exists( 'pixel_id', $stsp_settings )) { 42 if( 43 $stsp_settings 44 && array_key_exists( 'pixel_id', $stsp_settings ) 45 && array_key_exists( 'pixel_enabled', $stsp_settings ) 46 && $stsp_settings['pixel_enabled'] === true 47 && $stsp_settings['pixel_id'] !== null 48 ) { 43 49 return $stsp_settings['pixel_id']; 44 50 } -
storespot/tags/1.1.0/readme.txt
r1982419 r2042059 3 3 Tags: woocommerce, facebook, dynamic ads, retargeting, woocommerce marketing, remarketing 4 4 Requires at least: 4.4.0 5 Tested up to: 4.95 Tested up to: 5.1 6 6 Requires PHP: 5.6 7 Stable tag: 1. 0.107 Stable tag: 1.1.0 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 50 50 == Changelog == 51 51 52 = 1.0.10 = 53 * Bug fixes for add to cart events and purchase events 54 * Support for combined category events 52 = 1.1.0 = 53 * Fix add-to-cart events with ajax 54 * Improved product and category matching 55 * Improved memory usage in feed generation 55 56 56 = 1.0.9 = 57 * Add category view to pixel data 58 * Remove options after plugin deactivation 59 60 = 1.0.8 = 61 * Improve memory usage in feed generation 62 63 = 1.0.7 = 64 * Compatibility with Facebook for WooCommerce plugin 65 66 = 1.0.6 = 67 * Use pagination on feed generation 68 69 = 1.0.5 = 70 * Add registration button to welcome message 71 * Add error handling and default fields in product feed 72 73 = 1.0.4 = 74 * Fix product feed encoding 75 * Add brand names to feed 76 77 = 1.0.3 = 78 * Extended admin notices 79 * Add integration with official Facebook plugin 80 81 = 1.0.2 = 82 * Upgrade WooCommerce REST API to v2 83 84 = 1.0.1 = 85 * Update description. 86 * Add plugin banner. 87 * Rename plugin. 88 89 = 1.0.0 = 90 * Initial release. 57 = 1.0 = 58 * Beta release -
storespot/tags/1.1.0/storespot.php
r1982419 r2042059 4 4 * Plugin URI: https://storespot.io/ 5 5 * Description: Stop leaving money on the table. Automate your retargeting ads with StoreSpot. 6 * Version: 1. 0.106 * Version: 1.1.0 7 7 * Author: StoreSpot 8 8 **/ … … 11 11 if ( ! defined( 'WPINC' ) ) { die; } 12 12 13 define( 'STORESPOT_VERSION', '1. 0.10' );13 define( 'STORESPOT_VERSION', '1.1.0' ); 14 14 15 15 function activate_storespot() { -
storespot/trunk/admin/class-storespot-api.php
r1969706 r2042059 16 16 'permission_callback' => array( $this, 'get_settings_permission_check' ), 17 17 )); 18 19 register_rest_route( $this->namespace, '/storespot/feed/', array( 20 'methods' => WP_REST_SERVER::READABLE, 21 'callback' => array( $this, 'update_storespot_feed' ), 22 'permission_callback' => array( $this, 'get_settings_permission_check' ), 23 ) ); 18 24 } 19 25 … … 30 36 } 31 37 32 public function update_storespot_settings($request) {33 $settings = $request['settings'];34 update_option( 'storespot_settings', $settings );35 if ( ! wp_next_scheduled( 'stsp_product_feed_update' ) ) {36 wp_schedule_event( time(), 'hourly', 'stsp_product_feed_update' );37 }38 39 $data = array( 'updated' => true, 'settings' => get_option( 'storespot_settings' ) );40 $response = rest_ensure_response($data);41 $response->set_status(200);42 43 return $response;44 }45 46 38 public function get_settings_permission_check() { 47 39 if ( !wc_rest_check_user_permissions('read') ) { … … 56 48 } 57 49 58 public function get_storespot_settings($request) { 59 if ( wp_next_scheduled( 'stsp_product_feed_update' ) ) { 60 $cronjob = date( 61 'Y-m-d h:i:s', 62 wp_next_scheduled( 'stsp_product_feed_update' ) 63 ); 64 } else { 65 $cronjob = false; 50 public function update_storespot_settings($request) { 51 $new_settings = $request['settings']; 52 $current_settings = get_option( 'storespot_settings' ); 53 54 foreach( $new_settings as $key => $value ) { 55 $current_settings[$key] = $value; 66 56 } 67 57 68 if ( ! function_exists( 'get_plugins' ) ) { 69 require_once ABSPATH . 'wp-admin/includes/plugin.php'; 70 } 58 $updated = update_option( 'storespot_settings', $current_settings ); 59 $data = array( 'updated' => $updated ); 71 60 72 $plugins = get_plugins(); 73 $plugins_view = array(); 74 foreach( $plugins as $plugin ) { 75 array_push($plugins_view, array( 76 'name' => $plugin['Name'], 77 'version' => $plugin['Version'], 78 )); 79 } 61 $response = rest_ensure_response($data); 62 $response->set_status(200); 63 return $response; 64 } 80 65 66 public function get_storespot_settings($request) { 81 67 $data = array( 82 'cronjob' => $cronjob, 83 'plugin_version' => STORESPOT_VERSION, 84 'settings' => get_option( ' storespot_settings' ), 85 'wp_version' => get_bloginfo( 'version' ), 86 'wc_version' => get_option( 'woocommerce_version' ), 87 'plugins' => $plugins_view, 68 'settings' => get_option( 'storespot_settings' ), 69 'feed' => get_option( 'storespot_feed' ), 70 'stsp_version' => STORESPOT_VERSION, 71 'wp_version' => get_bloginfo( 'version' ), 72 'wc_version' => get_option( 'woocommerce_version' ), 88 73 ); 89 74 90 75 $response = rest_ensure_response($data); 91 76 $response->set_status(200); 77 return $response; 78 } 92 79 80 public function update_storespot_feed() { 81 do_action('stsp_call_async_feed_update'); 82 $response = rest_ensure_response(array( 'received' => true )); 83 $response->set_status(200); 93 84 return $response; 94 85 } -
storespot/trunk/admin/class-storespot-productfeed.php
r1977618 r2042059 7 7 protected $feed_items = null; 8 8 protected $factory = null; 9 protected $url = null; 9 protected $url = null; 10 protected $writer = null; 10 11 protected $chunk_size = 0; 11 protected $offset = 0;12 protected $offset = 0; 12 13 protected $settings = array(); 13 protected $store = array();14 protected $store = array(); 14 15 15 16 public function __construct() { 16 17 17 18 $this->chunk_size = $this->stsp_get_chunk_size(); 18 $this->settings = $this->stsp_get_settings();19 $this->store = array(19 $this->settings = $this->stsp_get_settings(); 20 $this->store = array( 20 21 'name' => get_bloginfo( 'name' ), 21 22 'url' => get_site_url(), … … 32 33 $upload_dir = $this->upload_directory(); 33 34 $dir_path = $upload_dir['dir_path']; 34 $path = $upload_dir['file_path'];35 $path = $upload_dir['file_path']; 35 36 $this->url = $upload_dir['file_url']; 36 37 37 if ( file_exists( $dir_path ) ) { 38 $fp = fopen( $path, 'w' ); 39 fwrite( $fp, $this->stsp_create_feed() ); 40 fclose( $fp ); 41 } 42 38 $tmp = $path.".tmp"; 39 if (file_exists( $tmp )) { 40 unlink( $tmp ); 41 } 42 43 if ( $this->settings['feed'] === true && file_exists( $dir_path ) ) { 44 $this->stsp_create_feed($tmp); 45 } 46 47 rename($path . ".tmp", $path); 43 48 return $this->url; 44 49 } … … 47 52 48 53 $wp_upload_dir = wp_upload_dir(); 49 $basedir = $wp_upload_dir['basedir'];50 $baseurl = $wp_upload_dir['baseurl'];54 $basedir = $wp_upload_dir['basedir']; 55 $baseurl = $wp_upload_dir['baseurl']; 51 56 $storespot_dir = $basedir . '/storespot/'; 52 57 $storespot_url = $baseurl . '/storespot/'; … … 73 78 74 79 $settings = array( 75 'pixel_id' => null, 76 'category' => null, 80 'category' => null, 81 'feed' => false, 82 'start_memory' => null, 83 'end_memory' => null, 77 84 ); 78 85 $config = get_option( 'storespot_settings', array() ); … … 81 88 $settings['category'] = $config['product_category']; 82 89 } 83 if( array_key_exists( ' pixel_id', $config ) ) {84 $settings[' pixel_id'] = $config['pixel_id'];90 if( array_key_exists( 'feed_enabled', $config ) ) { 91 $settings['feed'] = $config['feed_enabled']; 85 92 } 86 93 } … … 107 114 if ( function_exists( 'wc_get_products' ) ) { 108 115 $args = array( 109 'status' => array( 'publish' ), 110 'type' => array( 'simple', 'variable', 'bundle', 'composite' ), 111 'offset' => $this->offset, 112 'limit' => $this->chunk_size, 116 'status' => array( 'publish' ), 117 'offset' => $this->offset, 118 'limit' => $this->chunk_size, 113 119 ); 114 120 return array( 'wc_get_products', $args ); 115 121 } else { 116 122 $args = array( 117 'post_type' => 'product',118 'offset' => $this->offset,119 'numberposts' => $this->chunk_size,123 'post_type' => 'product', 124 'offset' => $this->offset, 125 'numberposts' => $this->chunk_size, 120 126 ); 121 127 return array( 'get_posts', $args ); … … 124 130 } 125 131 126 private function stsp_create_feed() { 127 128 // Log every feed start 129 error_log( 130 "\n" . date('Y-m-d h:i:s'). " :: starting feed write", 131 3, 132 $this->log_file() 133 ); 134 135 // Make header first 136 $output = ""; 137 $output .= $this->stsp_render_header(); 138 139 // Render entries 132 private function stsp_create_feed($file) { 133 error_log("\n".date('Y-m-d h:i:s')." :: starting feed write",3,$this->log_file()); 134 135 $this->settings['start_memory'] = memory_get_peak_usage(); 136 $this->writer = new XMLWriter(); 137 $this->writer->openMemory(); 138 $this->writer->startDocument('1.0', 'UTF-8'); 139 $this->stsp_render_header(); 140 140 141 $this->factory = new WC_Product_Factory(); 141 142 list($query, $args) = $this->stsp_create_query(); … … 144 145 $products = $query( $args ); 145 146 while ( count( $products ) ) { 146 147 147 // Process products in query 148 148 foreach ( $products as $product ) { 149 $output .= $this->stsp_render_entry( $product ); 150 } 151 152 // Flush internal cache for memory optimization 153 if ( ! wp_using_ext_object_cache() ) { 154 wp_cache_flush(); 149 $this->stsp_render_entry( $product ); 155 150 } 156 151 … … 158 153 $args['offset'] += $this->chunk_size; 159 154 $products = $query( $args ); 160 } 161 162 // Make footer 163 $output .= $this->stsp_render_footer(); 164 165 // Log every feed end 166 error_log( 167 "\n" . date('Y-m-d h:i:s'). " :: completed feed write", 168 3, 169 $this->log_file() 170 ); 171 172 return $output; 155 156 // Write & flush 157 file_put_contents($file, $this->writer->flush(true), FILE_APPEND); 158 } 159 160 $this->settings['end_memory'] = memory_get_peak_usage(); 161 162 $this->stsp_render_footer(); 163 file_put_contents($file, $this->writer->flush(true), FILE_APPEND); 164 error_log("\n".date('Y-m-d h:i:s')." :: completed feed write",3,$this->log_file()); 173 165 } 174 166 175 167 private function stsp_render_header() { 176 177 $header = ""; 178 $header .= "<?xml version='1.0' encoding='UTF-8' ?>\n"; 179 $header .= "<feed xmlns='http://www.w3.org/2005/Atom' xmlns:g='http://base.google.com/ns/1.0'>\n"; 180 $header .= " <title><![CDATA[" . $this->store['name'] . " - Facebook Product Feed]]></title>\n"; 181 $header .= " <link rel='self' href='" . $this->url . "'/>\n"; 182 return $header; 183 168 // Start feed 169 $this->writer->startElement('feed'); 170 $this->writer->writeAttribute('xmlns', 'http://www.w3.org/2005/Atom'); 171 $this->writer->writeAttribute('xmlns:g', 'http://base.google.com/ns/1.0'); 172 173 // Add title 174 $this->writer->startElement('title'); 175 $this->writer->writeCData($this->store['name'] . " - Facebook Product Feed"); 176 $this->writer->endElement(); 177 178 // Add link 179 $this->writer->startElement('link'); 180 $this->writer->writeAttribute('rel', 'self'); 181 $this->writer->writeAttribute('href', $this->url); 182 $this->writer->endElement(); 184 183 } 185 184 186 185 private function stsp_render_footer() { 187 188 return '</feed>'; 186 $this->writer->endElement(); 187 $this->writer->writeComment('Created: ' . date('Y-m-d H:i:s', time())); 188 $this->writer->writeComment('Start memory: ' . round( $this->settings['start_memory'] / 1024 / 1024, 2 ) . ' MB'); 189 $this->writer->writeComment('End memory: ' . round( $this->settings['end_memory'] / 1024 / 1024, 2 ) . ' MB'); 189 190 190 191 } … … 219 220 private function stsp_variable_product( $product ) { 220 221 $variations = $product->get_available_variations(); 221 $output = '';222 222 foreach ( $variations as $variation ) { 223 223 $variation_id = $variation['variation_id']; 224 224 $variation = $this->factory->get_product( $variation_id ); 225 $ output .= $this->stsp_render_product( $variation, $product );226 } 227 return $output;225 $this->stsp_render_product( $variation, $product ); 226 } 227 return; 228 228 } 229 229 230 230 private function stsp_render_product( $product, $parent=null ) { 231 231 232 $image_link = $this->render_image_link( $product );232 $image_link = $this->render_image_link( $product ); 233 233 if( ! $image_link ) { 234 234 if( ! $parent ) … … 243 243 $product_id = $product->get_id(); 244 244 $product_sku = $product->get_sku(); 245 $feed_id = $product_sku ? 246 $product_sku . '_' . $product_id : 247 'wc_post_id_' . $product_id; 248 249 $group_id = $parent ? $parent->get_id() : null; 250 $product_name = $product->get_name(); 251 $product_price= $product->get_price() . ' ' . $this->settings['currency']; 245 $feed_id = 'stsp_' . $product_id; 246 247 $group_id = $parent ? 'stsp_' . $parent->get_id() : null; 248 $product_name = ucwords(strtolower($product->get_name())); 249 $product_price = $product->get_price() . ' ' . $this->settings['currency']; 252 250 $description = $this->render_description( $product ); 253 $availability = $this->render_availability( $product );251 $availability = $this->render_availability( $product ); 254 252 $condition = 'new'; 255 253 $image_link = $this->render_image_link( $product ); 256 254 $additional = $this->render_additional_images( $product ); 257 $brand = $this->render_brand( $product);258 $link = $this->render_product_link( $product );255 $brand = $this->render_brand( $product_id ); 256 $link = $this->render_product_link( $product ); 259 257 $sale_price = ( $product->is_on_sale() && $product->get_sale_price() ) ? 260 $product->get_sale_price() . ' ' . $this->settings['currency'] :261 null;258 $product->get_sale_price() . ' ' . $this->settings['currency'] : 259 null; 262 260 $sale_from = $product->get_date_on_sale_from(); 263 $sale_to = $product->get_date_on_sale_to();261 $sale_to = $product->get_date_on_sale_to(); 264 262 265 263 // Fixes for product variations … … 282 280 283 281 // Render output 284 $output = ""; 285 $output .= " <entry>\n"; 286 $output .= " <g:id>" . $feed_id . "</g:id>\n"; 287 $output .= " <g:title><![CDATA[" . $title . "]]></g:title>\n"; 288 $output .= " <g:description><![CDATA[" . $description . "]]></g:description>\n"; 289 $output .= " <g:availability>" . $availability . "</g:availability>\n"; 290 $output .= " <g:condition>" . $condition . "</g:condition>\n"; 291 $output .= " <g:link>" . $link . "</g:link>\n"; 292 $output .= " <g:price>" . $product_price . "</g:price>\n"; 293 $output .= " <g:brand><![CDATA[" . $brand . "]]></g:brand>\n"; 294 $output .= " <g:image_link><![CDATA[" . $image_link . "]]></g:image_link>\n"; 282 $this->writer->startElement('entry'); 283 $this->writer->writeElement('g:id', $feed_id); 284 $this->writer->startElement('g:title');$this->writer->writeCData($title);$this->writer->endElement(); 285 $this->writer->startElement('g:description');$this->writer->writeCData($description);$this->writer->endElement(); 286 $this->writer->writeElement('g:availability', $availability); 287 $this->writer->writeElement('g:condition', $condition); 288 $this->writer->writeElement('g:link', $link); 289 $this->writer->writeElement('g:price', $product_price); 290 $this->writer->startElement('g:brand');$this->writer->writeCData($brand);$this->writer->endElement(); 291 $this->writer->startElement('g:image_link');$this->writer->writeCData($image_link);$this->writer->endElement(); 295 292 296 293 if( $group_id ) { 297 $ output .= " <g:item_group_id>" . $group_id . "</g:item_group_id>\n";298 } 299 300 if( $additional _image_link) {301 $ output .= " <g:additional_image_link><![CDATA[" . $additional_image_link . "]]></g:additional_image_link>\n";294 $this->writer->writeElement('g:item_group_id', $group_id); 295 } 296 297 if( $additional ) { 298 $this->writer->startElement('g:additional_image_link');$this->writer->writeCData($additional);$this->writer->endElement(); 302 299 } 303 300 304 301 if( $sale_price ) { 305 $ output .= " <g:sale_price><![CDATA[" . $sale_price . "]]></g:sale_price>\n";302 $this->writer->writeElement('g:sale_price', $sale_price); 306 303 } 307 304 308 305 if( $sale_from ) { 309 $ output .= " <g:sale_price_start_date><![CDATA[" . $sale_from . "]]></g:sale_price_start_date>\n";306 $this->writer->startElement('g:sale_price_start_date');$this->writer->writeCData($sale_from);$this->writer->endElement(); 310 307 } 311 308 312 309 if( $sale_to ) { 313 $ output .= " <g:sale_price_end_date><![CDATA[" . $sale_to . "]]></g:sale_price_end_date>\n";310 $this->writer->startElement('g:sale_price_end_date');$this->writer->writeCData($sale_to);$this->writer->endElement(); 314 311 } 315 312 316 313 if( $this->settings['category'] ) { 317 $output .= " <g:google_product_category><![CDATA[" . $this->settings['category'] . "]]></g:google_product_category>\n"; 318 } 319 320 $output .= " </entry>\n"; 321 322 return $output; 314 $this->writer->writeElement('g:google_product_category', $this->settings['category']); 315 } 316 317 $this->writer->endElement(); 318 return; 323 319 } 324 320 … … 370 366 private function render_additional_images( $product ) { 371 367 $gallery_image_ids = $product->get_gallery_image_ids(); 368 $additional_image_link = null; 372 369 if ( $gallery_image_ids ) { 373 370 $i = 0; … … 406 403 } 407 404 408 private function render_brand( $product ) {405 private function render_brand( $product_id ) { 409 406 $term_names = wp_get_post_terms( 410 407 $product_id, 'brand', array('orderby'=>'name', 'fields' => 'names') -
storespot/trunk/includes/class-storespot-activator.php
r1957373 r2042059 7 7 $stsp_settings = get_option('storespot_settings'); 8 8 9 if( $stsp_settings && array_key_exists( 'product_feed', $stsp_settings )) { 10 $feed = $stsp_settings['product_feed']; 11 if ( $feed && !wp_next_scheduled( 'stsp_product_feed_update' ) ) { 12 wp_schedule_event( time(), 'hourly', 'stsp_product_feed_update' ); 13 } 14 } else { 9 if( !$stsp_settings ) { 15 10 $options = [ 16 'pixel_id' => '', 17 'product_feed' => 'no', 18 'product_category' => '' 11 'pixel_id' => null, 12 'pixel_enabled' => false, 13 'feed_enabled' => false, 14 'product_category' => 0, 19 15 ]; 20 21 16 add_option( 'storespot_settings', $options ); 17 add_option( 'storespot_feed', null ); 22 18 } 23 19 -
storespot/trunk/includes/class-storespot-deactivator.php
r1977618 r2042059 2 2 class StoreSpot_Deactivator { 3 3 public static function deactivate() { 4 wp_clear_scheduled_hook( 'stsp_product_feed_update' );5 4 delete_option( 'storespot_settings' ); 5 delete_option( 'storespot_feed' ); 6 6 } 7 7 } -
storespot/trunk/includes/class-storespot.php
r1977618 r2042059 22 22 $this->version = STORESPOT_VERSION; 23 23 } else { 24 $this->version = ' 1.0.0';24 $this->version = '0.0.0'; 25 25 } 26 26 $this->plugin_name = 'storespot'; … … 46 46 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-messages.php'; 47 47 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-api.php'; 48 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-storespot-async.php'; 48 49 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-storespot-events.php'; 49 50 require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-storespot-facebook-pixel.php'; … … 55 56 ! class_exists( 'StoreSpot_API' ) || 56 57 ! class_exists( 'StoreSpot_Events' ) || 57 ! class_exists( 'StoreSpot_Facebook_Pixel' ) 58 ! class_exists( 'StoreSpot_Facebook_Pixel' ) || 59 ! class_exists( 'StoreSpot_Async' ) 58 60 ) { 59 61 return false; … … 65 67 66 68 private function define_admin_hooks() { 67 $product_feed = new StoreSpot_Product_Feed();68 69 $admin_message = new StoreSpot_Messages(); 69 $this->loader->add_action( 'stsp_product_feed_update', $product_feed, 'write_product_feed' ); 70 $async_request = new StoreSpot_Async(); 71 $products_feed = new StoreSpot_Product_Feed(); 70 72 $this->loader->add_action( 'admin_notices', $admin_message, 'activation_notice' ); 73 $this->loader->add_action( 'wp_ajax_' . $async_request->get_ajax_action(), $async_request, 'execute' ); 74 $this->loader->add_action( 'wp_ajax_nopriv_' . $async_request->get_ajax_action(), $async_request, 'execute' ); 75 $this->loader->add_action( 'stsp_call_async_feed_update', $async_request, 'call' ); 76 $this->loader->add_action( $async_request->get_feed_action(), $products_feed, 'write_product_feed' ); 71 77 } 72 78 … … 74 80 $plugin_public = new StoreSpot_Events( $this->get_plugin_name(), $this->get_version() ); 75 81 $pixel_id = $plugin_public->facebook_pixel->get_pixel_id(); 76 if( $pixel_id && ! $this->fb_integration_installed( $pixel_id )) {82 if( $pixel_id ) { 77 83 $this->loader->add_action( 'wp_head', $plugin_public, 'render_facebook_pixel' ); 78 $this->loader->add_action( 'wp_ head', $plugin_public, 'render_facebook_pixel_noscript' );84 $this->loader->add_action( 'wp_footer', $plugin_public, 'render_facebook_pixel_noscript' ); 79 85 $this->loader->add_action( 'woocommerce_after_single_product', $plugin_public, 'render_product_view_event'); 80 86 $this->loader->add_action( 'woocommerce_after_shop_loop', $plugin_public, 'render_category_view_event'); … … 84 90 $this->loader->add_action( 'woocommerce_after_checkout_form', $plugin_public, 'render_initiate_checkout_event' ); 85 91 $this->loader->add_action( 'woocommerce_thankyou', $plugin_public, 'render_purchase_event' ); 92 $this->loader->add_action( 'woocommerce_payment_complete', $plugin_public, 'render_purchase_event' ); 86 93 $this->loader->add_action( 'wp_footer', $plugin_public, 'custom_jquery_add_to_cart_script' ); 87 $this->loader->add_action( 'wc_ajax_ render_add_to_cart_event', $plugin_public, 'render_ajax_add_to_cart_event' );94 $this->loader->add_action( 'wc_ajax_stsp_add_to_cart_event', $plugin_public, 'render_ajax_add_to_cart_event' ); 88 95 } 89 96 } 90 97 91 private function fb_integration_installed($pixel_id) {92 $fb_option = get_option('facebook_config');93 $fb_integration_option_set = false;94 if ( $fb_option && array_key_exists( 'pixel_id', $fb_option ) ) {95 if ( $fb_option['pixel_id'] == $pixel_id) {96 $fb_integration_option_set = true;97 }98 }99 include_once( ABSPATH . 'wp-admin/includes/plugin.php' );100 $fb_integration_activated = class_exists('WC_Facebookcommerce');101 return $fb_integration_activated && $fb_integration_option_set;102 }103 104 98 private function define_api_hooks() { 105 $api = new StoreSpot_API();106 $this->loader->add_action( 'rest_api_init', $api, 'storespot_api_route');99 $api = new StoreSpot_API(); 100 $this->loader->add_action( 'rest_api_init', $api, 'storespot_api_route'); 107 101 } 108 102 -
storespot/trunk/public/class-storespot-events.php
r1982419 r2042059 18 18 public function get_facebook_content_id($product) { 19 19 $product_id = $product->get_id(); 20 $product_sku = $product->get_sku(); 21 $sku_id = $product_sku . '_' . $product_id; 22 $other_id = 'wc_post_id_' . $product_id; 23 24 $ids = array($other_id, $product_id); 25 if ( $product_sku ) { 26 $ids[] = $sku_id; 27 $ids[] = $product_sku; 28 } 29 30 return $ids; 20 return 'stsp_' . $product->get_id(); 31 21 } 32 22 … … 34 24 global $post; 35 25 $product = wc_get_product($post->ID); 26 $content_type = 'product'; 36 27 37 28 if ( $product ) { 29 if( $product->get_type() == 'variable' ) { 30 $content_type = 'product_group'; 31 } 38 32 $params = array(); 33 $params['content_ids'] = json_encode( [$this->get_facebook_content_id( $product )] ); 34 $params['content_type'] = $content_type; 35 $params['content_name'] = $product->get_title(); 36 $params['currency'] = get_woocommerce_currency(); 39 37 $params['value'] = $product->get_price(); 40 $params['content_name'] = $product->get_title();41 $params['content_type'] = ($product->get_type() == 'variable' ? 'product_group' : 'product');42 $params['currency'] = get_woocommerce_currency();43 $params['content_ids'] = json_encode( $this->get_facebook_content_id( $product ) );44 38 45 39 $this->facebook_pixel->event_code( 'ViewContent', $params ); … … 53 47 54 48 $products = array_values(array_map(function($item) { 55 return wc_get_product($item->ID);56 }, $wp_query->posts));49 return wc_get_product($item->ID); 50 }, $wp_query->posts)); 57 51 58 52 $content_type = 'product'; … … 60 54 foreach ($products as $product) { 61 55 if (!$product) { continue; } 62 $product_ids = array_merge( 63 $product_ids, 64 $this->get_facebook_content_id($product) 65 ); 66 if ($product->get_type() == 'variable') { 67 $content_type = 'product_group'; 68 } 69 } 70 71 $category_path = wp_get_post_terms( get_the_ID(), 'product_cat' ); 56 if ( $product->get_type() == 'variable' ) { continue; } 57 $product_ids[] = $this->get_facebook_content_id($product); 58 } 59 60 $category_path = wp_get_post_terms( get_the_ID(), 'product_cat' ); 72 61 $content_category = array_values( array_map( function($item) { 73 62 return $item->name; … … 81 70 82 71 $params = array( 83 'content_name' => json_encode($categories['name']),72 'content_name' => json_encode($categories['name']), 84 73 'content_category' => json_encode($categories['categories']), 85 'content_ids' => json_encode(array_slice($product_ids, 0, 10)),86 'content_type' => $content_type74 'content_ids' => json_encode($product_ids), 75 'content_type' => $content_type 87 76 ); 88 77 … … 112 101 $product_ids = array(); 113 102 foreach ( $products as $item ) { 114 $product_ids = array_merge( 115 $product_ids, 116 $this->get_facebook_content_id( $item['data'] ) 117 ); 103 $product_ids[] = $this->get_facebook_content_id( $item['data'] ); 118 104 } 119 105 … … 134 120 135 121 public function render_ajax_add_to_cart_event() { 122 136 123 global $woocommerce; 137 124 $products = $woocommerce->cart->get_cart(); 125 126 ob_start(); 127 138 128 $product_ids = array(); 139 129 foreach ( $products as $item ) { 140 $product_ids = array_merge( 141 $product_ids, 142 $this->get_facebook_content_id( $item['data'] ) 143 ); 144 } 130 $product_ids[] = $this->get_facebook_content_id( $item['data'] ); 131 } 132 145 133 $params = array(); 146 134 $params['content_ids'] = json_encode( $product_ids ); … … 149 137 $params['currency'] = get_woocommerce_currency(); 150 138 151 $code = $this->facebook_pixel->ajax_event_code( 'AddToCart', $params ); 152 wp_send_json($code); 139 echo $this->facebook_pixel->ajax_event_code( 'AddToCart', $params ); 140 141 $pixel = ob_get_clean(); 142 wp_send_json($pixel); 153 143 } 154 144 … … 162 152 $product_ids = array(); 163 153 foreach ( $products as $item ) { 164 $product_ids = array_merge( 165 $product_ids, 166 $this->get_facebook_content_id( $item['data'] ) 167 ); 154 $product_id[] = $this->get_facebook_content_id( $item['data'] ); 168 155 } 169 156 … … 184 171 185 172 $order = wc_get_order( $order_id ); 173 $content_type = 'product'; 186 174 $product_ids = array(); 187 175 foreach ( $order->get_items() as $item ) { 188 176 $product = $item->get_product(); 189 $product_ids = array_merge(190 $product_ids, 191 $this->get_facebook_content_id( $product ) 192 );193 } 194 195 $params = array(); 196 $params['content_ids'] = json_encode( $product_ids ); 197 $params['content_type'] = 'product';177 $product_ids[] = $this->get_facebook_content_id( $product ); 178 if( $product->get_type() == 'variable' ) { 179 $content_type = 'product_group'; 180 } 181 } 182 183 $params = array(); 184 $params['content_ids'] = json_encode( $product_ids ); 185 $params['content_type'] = $content_type; 198 186 $params['value'] = $order->get_total(); 199 187 $params['currency'] = get_woocommerce_currency(); … … 203 191 204 192 public function custom_jquery_add_to_cart_script(){ 205 if ( is_shop() || is_product_category() || is_product_tag() ): 206 ?> 207 <script type="text/javascript"> 208 (function($){ 209 $( document.body ).on( 'added_to_cart', function(){ 210 $.get('?wc-ajax=render_add_to_cart_event', function(script) { 211 console.log(script); 212 $('head').append(script); 213 }); 214 }); 215 })(jQuery); 216 </script> 217 <?php 218 endif; 193 if ( is_front_page() || is_shop() || is_product_category() || is_product_tag() ) { 194 195 echo " 196 <!-- StoreSpot Facebook Listener Begin --> 197 <script type='text/javascript'> 198 document.addEventListener('DOMContentLoaded', function() { 199 jQuery && jQuery(function($){ 200 $('body').on('added_to_cart', function(event) { 201 // Ajax action. 202 $.get('?wc-ajax=stsp_add_to_cart_event', function(data) { 203 $('head').append(data); 204 }); 205 }); 206 }); 207 }, false); 208 </script> 209 <!-- StoreSpot Facebook Listener End --> 210 "; 211 212 } 219 213 } 220 214 } -
storespot/trunk/public/class-storespot-facebook-pixel.php
r1969706 r2042059 40 40 public function get_pixel_id() { 41 41 $stsp_settings = get_option( 'storespot_settings' ); 42 if( $stsp_settings && array_key_exists( 'pixel_id', $stsp_settings )) { 42 if( 43 $stsp_settings 44 && array_key_exists( 'pixel_id', $stsp_settings ) 45 && array_key_exists( 'pixel_enabled', $stsp_settings ) 46 && $stsp_settings['pixel_enabled'] === true 47 && $stsp_settings['pixel_id'] !== null 48 ) { 43 49 return $stsp_settings['pixel_id']; 44 50 } -
storespot/trunk/readme.txt
r1982419 r2042059 3 3 Tags: woocommerce, facebook, dynamic ads, retargeting, woocommerce marketing, remarketing 4 4 Requires at least: 4.4.0 5 Tested up to: 4.95 Tested up to: 5.1 6 6 Requires PHP: 5.6 7 Stable tag: 1. 0.107 Stable tag: 1.1.0 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html … … 50 50 == Changelog == 51 51 52 = 1.0.10 = 53 * Bug fixes for add to cart events and purchase events 54 * Support for combined category events 52 = 1.1.0 = 53 * Fix add-to-cart events with ajax 54 * Improved product and category matching 55 * Improved memory usage in feed generation 55 56 56 = 1.0.9 = 57 * Add category view to pixel data 58 * Remove options after plugin deactivation 59 60 = 1.0.8 = 61 * Improve memory usage in feed generation 62 63 = 1.0.7 = 64 * Compatibility with Facebook for WooCommerce plugin 65 66 = 1.0.6 = 67 * Use pagination on feed generation 68 69 = 1.0.5 = 70 * Add registration button to welcome message 71 * Add error handling and default fields in product feed 72 73 = 1.0.4 = 74 * Fix product feed encoding 75 * Add brand names to feed 76 77 = 1.0.3 = 78 * Extended admin notices 79 * Add integration with official Facebook plugin 80 81 = 1.0.2 = 82 * Upgrade WooCommerce REST API to v2 83 84 = 1.0.1 = 85 * Update description. 86 * Add plugin banner. 87 * Rename plugin. 88 89 = 1.0.0 = 90 * Initial release. 57 = 1.0 = 58 * Beta release -
storespot/trunk/storespot.php
r1982419 r2042059 4 4 * Plugin URI: https://storespot.io/ 5 5 * Description: Stop leaving money on the table. Automate your retargeting ads with StoreSpot. 6 * Version: 1. 0.106 * Version: 1.1.0 7 7 * Author: StoreSpot 8 8 **/ … … 11 11 if ( ! defined( 'WPINC' ) ) { die; } 12 12 13 define( 'STORESPOT_VERSION', '1. 0.10' );13 define( 'STORESPOT_VERSION', '1.1.0' ); 14 14 15 15 function activate_storespot() {
Note: See TracChangeset
for help on using the changeset viewer.