delete( 'products', [ 'id' => $product_id ] ); return true; } static public function delete_products( $product_ids ) { global $mdb; if ( empty( $product_ids ) || !is_array( $product_ids ) ) { return false; } foreach ( $product_ids as $product_id ) { $mdb -> delete( 'products', [ 'id' => $product_id ] ); } return true; } static public function get_product_comments( $product_id ) { global $mdb; return $mdb -> query( 'SELECT id, comment, date_add FROM products_comments WHERE product_id = \'' . $product_id . '\' ORDER BY date_add DESC' ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function delete_product_comment( $comment_id ) { global $mdb; return $mdb -> delete( 'products_comments', [ 'id' => $comment_id ] ); } static public function get_product_comment_by_date( $product_id, $date ) { global $mdb; return $mdb -> get( 'products_comments', [ 'id', 'comment' ], [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] ); } static public function get_min_roas( $product_id ) { global $mdb; return $mdb -> get( 'products', 'min_roas', [ 'id' => $product_id ] ); } static public function get_client_bestseller_min_roas( $client_id ) { global $mdb; return $mdb -> get( 'clients', 'bestseller_min_roas', [ 'id' => $client_id ] ); } static public function save_client_bestseller_min_roas( $client_id, $min_roas ) { global $mdb; return $mdb -> update( 'clients', [ 'bestseller_min_roas' => $min_roas ], [ 'id' => $client_id ] ); } static public function save_min_roas( $product_id, $min_roas ) { global $mdb; return $mdb -> update( 'products', [ 'min_roas' => $min_roas ], [ 'id' => $product_id ] ); } static private function build_scope_filters( &$sql, &$params, $campaign_id, $ad_group_id ) { $campaign_id = (int) $campaign_id; $ad_group_id = (int) $ad_group_id; if ( $campaign_id > 0 ) { $sql .= ' AND pt.campaign_id = :campaign_id'; $params[':campaign_id'] = $campaign_id; } if ( $ad_group_id > 0 ) { $sql .= ' AND pt.ad_group_id = :ad_group_id'; $params[':ad_group_id'] = $ad_group_id; } } static public function get_products( $client_id, $search, $limit, $start, $order_name, $order_dir, $campaign_id = 0, $ad_group_id = 0 ) { global $mdb; $limit = max( 1, (int) $limit ); $start = max( 0, (int) $start ); $order_dir = strtoupper( (string) $order_dir ) === 'ASC' ? 'ASC' : 'DESC'; $order_map = [ 'offer_id' => 'offer_id', 'campaign_name' => 'campaign_name', 'ad_group_name' => 'ad_group_name', 'name' => 'name', 'impressions' => 'impressions', 'impressions_30' => 'impressions_30', 'clicks' => 'clicks', 'clicks_30' => 'clicks_30', 'ctr' => 'ctr', 'cost' => 'cost', 'cpc' => 'cpc', 'conversions' => 'conversions', 'conversions_value' => 'conversions_value', 'roas' => 'roas', 'min_roas' => 'min_roas' ]; $order_sql = $order_map[ $order_name ] ?? 'clicks'; $params = [ ':client_id' => (int) $client_id ]; $sql = 'SELECT p.id AS product_id, p.offer_id, p.min_roas, pt.campaign_id, CASE WHEN COUNT( DISTINCT pt.campaign_id ) > 1 THEN \'--- wiele kampanii ---\' ELSE COALESCE( MAX( c.campaign_name ), \'--- brak kampanii ---\' ) END AS campaign_name, CASE WHEN COUNT( DISTINCT pt.ad_group_id ) > 1 THEN \'--- wiele grup reklam ---\' WHEN MAX( pt.ad_group_id ) = 0 THEN \'PMax (bez grup reklam)\' ELSE COALESCE( MAX( ag.ad_group_name ), \'--- brak grupy reklam ---\' ) END AS ad_group_name, CASE WHEN COUNT( DISTINCT pt.ad_group_id ) = 1 THEN MAX( pt.ad_group_id ) ELSE 0 END AS ad_group_id, MAX( pt.name ) AS name, SUM( pt.impressions ) AS impressions, SUM( pt.impressions_30 ) AS impressions_30, SUM( pt.clicks ) AS clicks, SUM( pt.clicks_30 ) AS clicks_30, CASE WHEN SUM( pt.impressions ) > 0 THEN ROUND( SUM( pt.clicks ) / SUM( pt.impressions ) * 100, 2 ) ELSE 0 END AS ctr, SUM( pt.cost ) AS cost, CASE WHEN SUM( pt.clicks ) > 0 THEN ROUND( SUM( pt.cost ) / SUM( pt.clicks ), 6 ) ELSE 0 END AS cpc, SUM( pt.conversions ) AS conversions, SUM( pt.conversions_value ) AS conversions_value, CASE WHEN SUM( pt.cost ) > 0 THEN ROUND( SUM( pt.conversions_value ) / SUM( pt.cost ) * 100, 2 ) ELSE 0 END AS roas FROM products_temp AS pt INNER JOIN products AS p ON p.id = pt.product_id LEFT JOIN campaigns AS c ON c.id = pt.campaign_id LEFT JOIN campaign_ad_groups AS ag ON ag.id = pt.ad_group_id WHERE p.client_id = :client_id'; self::build_scope_filters( $sql, $params, $campaign_id, $ad_group_id ); if ( $search ) { $sql .= ' AND ( pt.name LIKE :search OR p.offer_id LIKE :search OR c.campaign_name LIKE :search OR ag.ad_group_name LIKE :search )'; $params[':search'] = '%' . $search . '%'; } $sql .= ' GROUP BY p.id, p.offer_id, p.min_roas, pt.campaign_id'; $sql .= ' ORDER BY ' . $order_sql . ' ' . $order_dir . ', product_id DESC LIMIT ' . $start . ', ' . $limit; return $mdb -> query( $sql, $params ) -> fetchAll( \PDO::FETCH_ASSOC ); } public static function get_roas_bounds( int $client_id, ?string $search = null, int $campaign_id = 0, int $ad_group_id = 0 ): array { global $mdb; $params = [ ':client_id' => $client_id ]; $sql = 'SELECT MIN( p.min_roas ) AS min_roas, MAX( pt.roas ) AS max_roas FROM products_temp AS pt INNER JOIN products AS p ON p.id = pt.product_id LEFT JOIN campaigns AS c ON c.id = pt.campaign_id LEFT JOIN campaign_ad_groups AS ag ON ag.id = pt.ad_group_id WHERE p.client_id = :client_id AND pt.conversions > 10'; self::build_scope_filters( $sql, $params, $campaign_id, $ad_group_id ); if ( $search ) { $sql .= ' AND ( pt.name LIKE :search OR p.offer_id LIKE :search OR c.campaign_name LIKE :search OR ag.ad_group_name LIKE :search )'; $params[':search'] = '%' . $search . '%'; } $row = $mdb -> query( $sql, $params ) -> fetch( \PDO::FETCH_ASSOC ); return [ 'min' => isset( $row['min_roas'] ) ? (float) $row['min_roas'] : 0.0, 'max' => isset( $row['max_roas'] ) ? (float) $row['max_roas'] : 0.0, ]; } static public function get_records_total_products( $client_id, $search, $campaign_id = 0, $ad_group_id = 0 ) { global $mdb; $params = [ ':client_id' => (int) $client_id ]; $sql = 'SELECT COUNT(0) FROM ( SELECT p.id, pt.campaign_id FROM products_temp AS pt INNER JOIN products AS p ON p.id = pt.product_id LEFT JOIN campaigns AS c ON c.id = pt.campaign_id LEFT JOIN campaign_ad_groups AS ag ON ag.id = pt.ad_group_id WHERE p.client_id = :client_id'; self::build_scope_filters( $sql, $params, $campaign_id, $ad_group_id ); if ( $search ) { $sql .= ' AND ( pt.name LIKE :search OR p.offer_id LIKE :search OR c.campaign_name LIKE :search OR ag.ad_group_name LIKE :search )'; $params[':search'] = '%' . $search . '%'; } $sql .= ' GROUP BY p.id, pt.campaign_id ) AS grouped_rows'; return $mdb -> query( $sql, $params ) -> fetchColumn(); } static public function get_product_full_context( $product_id ) { global $mdb; return $mdb -> query( 'SELECT p.id, p.offer_id, p.name, p.min_roas, COALESCE( SUM( pt.impressions ), 0 ) AS impressions, COALESCE( SUM( pt.impressions_30 ), 0 ) AS impressions_30, COALESCE( SUM( pt.clicks ), 0 ) AS clicks, COALESCE( SUM( pt.clicks_30 ), 0 ) AS clicks_30, CASE WHEN COALESCE( SUM( pt.impressions ), 0 ) > 0 THEN ROUND( COALESCE( SUM( pt.clicks ), 0 ) / COALESCE( SUM( pt.impressions ), 0 ) * 100, 2 ) ELSE 0 END AS ctr, COALESCE( SUM( pt.cost ), 0 ) AS cost, CASE WHEN COALESCE( SUM( pt.clicks ), 0 ) > 0 THEN ROUND( COALESCE( SUM( pt.cost ), 0 ) / COALESCE( SUM( pt.clicks ), 0 ), 6 ) ELSE 0 END AS cpc, COALESCE( SUM( pt.conversions ), 0 ) AS conversions, COALESCE( SUM( pt.conversions_value ), 0 ) AS conversions_value, CASE WHEN COALESCE( SUM( pt.cost ), 0 ) > 0 THEN ROUND( COALESCE( SUM( pt.conversions_value ), 0 ) / COALESCE( SUM( pt.cost ), 0 ) * 100, 2 ) ELSE 0 END AS roas FROM products AS p LEFT JOIN products_temp AS pt ON pt.product_id = p.id WHERE p.id = :pid GROUP BY p.id, p.offer_id, p.name, p.min_roas', [ ':pid' => $product_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function get_product_data( $product_id, $field ) { global $mdb; return $mdb -> get( 'products_data', $field, [ 'product_id' => $product_id ] ); } static public function get_product_merchant_context( $product_id ) { global $mdb; return $mdb -> query( 'SELECT p.id AS product_id, p.client_id, p.offer_id, cl.google_merchant_account_id FROM products AS p INNER JOIN clients AS cl ON cl.id = p.client_id WHERE p.id = :product_id LIMIT 1', [ ':product_id' => (int) $product_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function add_product_merchant_sync_log( $row ) { global $mdb; $data = [ 'product_id' => (int) ( $row['product_id'] ?? 0 ), 'field_name' => (string) ( $row['field_name'] ?? '' ), 'old_value' => isset( $row['old_value'] ) ? (string) $row['old_value'] : null, 'new_value' => isset( $row['new_value'] ) ? (string) $row['new_value'] : null, 'sync_status' => (string) ( $row['sync_status'] ?? 'pending' ), 'sync_source' => (string) ( $row['sync_source'] ?? 'products_ui' ), 'merchant_account_id' => isset( $row['merchant_account_id'] ) ? (string) $row['merchant_account_id'] : null, 'merchant_product_id' => isset( $row['merchant_product_id'] ) ? (string) $row['merchant_product_id'] : null, 'offer_id' => isset( $row['offer_id'] ) ? (string) $row['offer_id'] : null, 'api_response' => isset( $row['api_response'] ) ? (string) $row['api_response'] : null, 'error_message' => isset( $row['error_message'] ) ? (string) $row['error_message'] : null, 'date_add' => date( 'Y-m-d H:i:s' ) ]; if ( $data['product_id'] <= 0 || trim( $data['field_name'] ) === '' ) { return false; } return $mdb -> insert( 'products_merchant_sync_log', $data ); } static public function get_product_merchant_sync_logs( $product_id, $limit = 50 ) { global $mdb; $product_id = (int) $product_id; $limit = max( 1, (int) $limit ); if ( $product_id <= 0 ) { return []; } return $mdb -> query( 'SELECT id, field_name, old_value, new_value, sync_status, sync_source, merchant_account_id, merchant_product_id, offer_id, error_message, date_add FROM products_merchant_sync_log WHERE product_id = :product_id ORDER BY id DESC LIMIT ' . $limit, [ ':product_id' => $product_id ] ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function get_product_ads_keyword_context( $product_id ) { global $mdb; return $mdb -> query( 'SELECT p.id AS product_id, p.client_id, cl.google_ads_customer_id FROM products AS p INNER JOIN clients AS cl ON cl.id = p.client_id WHERE p.id = :product_id LIMIT 1', [ ':product_id' => (int) $product_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function get_cached_keyword_planner_terms( $product_id, $source_url, $limit = 15 ) { global $mdb; $product_id = (int) $product_id; $source_url = trim( (string) $source_url ); $limit = max( 1, (int) $limit ); if ( $product_id <= 0 || $source_url === '' ) { return []; } return $mdb -> query( 'SELECT keyword_text, avg_monthly_searches, competition, competition_index FROM products_keyword_planner_terms WHERE product_id = :product_id AND source_url = :source_url ORDER BY avg_monthly_searches DESC, keyword_text ASC LIMIT ' . $limit, [ ':product_id' => $product_id, ':source_url' => $source_url ] ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function replace_keyword_planner_terms( $product_id, $source_url, $customer_id, $terms ) { global $mdb; $product_id = (int) $product_id; $source_url = trim( (string) $source_url ); $customer_id = trim( (string) $customer_id ); $terms = is_array( $terms ) ? $terms : []; if ( $product_id <= 0 || $source_url === '' ) { return false; } $mdb -> delete( 'products_keyword_planner_terms', [ 'AND' => [ 'product_id' => $product_id, 'source_url' => $source_url ] ] ); if ( empty( $terms ) ) { return true; } foreach ( $terms as $term ) { $keyword_text = trim( (string) ( $term['keyword'] ?? '' ) ); if ( $keyword_text === '' ) { continue; } $mdb -> insert( 'products_keyword_planner_terms', [ 'product_id' => $product_id, 'source_url' => $source_url, 'keyword_text' => mb_substr( $keyword_text, 0, 255 ), 'avg_monthly_searches' => (int) ( $term['avg_monthly_searches'] ?? 0 ), 'competition' => $term['competition'] ?? null, 'competition_index' => isset( $term['competition_index'] ) ? (int) $term['competition_index'] : null, 'source_customer_id' => $customer_id !== '' ? $customer_id : null, 'date_add' => date( 'Y-m-d H:i:s' ) ] ); } return true; } static public function set_product_data( $product_id, $field, $value ) { global $mdb; if ( !$mdb -> count( 'products_data', [ 'product_id' => $product_id ] ) ) $result = $mdb -> insert( 'products_data', [ 'product_id' => $product_id, $field => $value ] ); else $result = $mdb -> update( 'products_data', [ $field => $value ], [ 'product_id' => $product_id ] ); return $result; } static public function get_product_history( $client_id, $product_id, $start, $limit, $campaign_id = 0, $ad_group_id = 0 ) { global $mdb; $limit = max( 1, (int) $limit ); $start = max( 0, (int) $start ); return $mdb -> query( 'SELECT MAX( ph.id ) AS id, SUM( ph.impressions ) AS impressions, SUM( ph.clicks ) AS clicks, CASE WHEN SUM( ph.impressions ) > 0 THEN ROUND( SUM( ph.clicks ) / SUM( ph.impressions ) * 100, 2 ) ELSE 0 END AS ctr, SUM( ph.cost ) AS cost, SUM( ph.conversions ) AS conversions, SUM( ph.conversions_value ) AS conversions_value, ph.date_add FROM products_history AS ph INNER JOIN products AS p ON p.id = ph.product_id WHERE ph.product_id = :product_id AND p.client_id = :client_id AND ph.campaign_id = :campaign_id AND ph.ad_group_id = :ad_group_id GROUP BY ph.date_add ORDER BY ph.date_add DESC LIMIT ' . $start . ', ' . $limit, [ ':product_id' => (int) $product_id, ':client_id' => (int) $client_id, ':campaign_id' => (int) $campaign_id, ':ad_group_id' => (int) $ad_group_id ] ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function get_records_total_product_history( $client_id, $product_id, $campaign_id = 0, $ad_group_id = 0 ) { global $mdb; return $mdb -> query( 'SELECT COUNT( DISTINCT ph.date_add ) FROM products_history AS ph INNER JOIN products AS p ON p.id = ph.product_id WHERE ph.product_id = :product_id AND p.client_id = :client_id AND ph.campaign_id = :campaign_id AND ph.ad_group_id = :ad_group_id', [ ':product_id' => (int) $product_id, ':client_id' => (int) $client_id, ':campaign_id' => (int) $campaign_id, ':ad_group_id' => (int) $ad_group_id ] ) -> fetchColumn(); } static public function get_product_history_30( $client_id, $product_id, $start, $limit, $campaign_id = 0, $ad_group_id = 0 ) { global $mdb; return $mdb -> query( 'SELECT ph3.* FROM products_history_30 AS ph3 INNER JOIN products AS p ON p.id = ph3.product_id WHERE ph3.product_id = :product_id AND p.client_id = :client_id AND ph3.campaign_id = :campaign_id AND ph3.ad_group_id = :ad_group_id ORDER BY ph3.date_add ASC LIMIT ' . (int) $start . ', ' . (int) $limit, [ ':product_id' => (int) $product_id, ':client_id' => (int) $client_id, ':campaign_id' => (int) $campaign_id, ':ad_group_id' => (int) $ad_group_id ] ) -> fetchAll( \PDO::FETCH_ASSOC ); } static public function get_impressions_30( $product_id, $campaign_id = null, $ad_group_id = null ) { global $mdb; $sql = 'SELECT COALESCE( SUM( impressions ), 0 ) AS total FROM products_history WHERE product_id = :product_id AND date_add >= :date_from'; $params = [ ':product_id' => (int) $product_id, ':date_from' => date( 'Y-m-d', strtotime( '-30 days', time() ) ) ]; if ( $campaign_id !== null ) { $sql .= ' AND campaign_id = :campaign_id'; $params[':campaign_id'] = (int) $campaign_id; } if ( $ad_group_id !== null ) { $sql .= ' AND ad_group_id = :ad_group_id'; $params[':ad_group_id'] = (int) $ad_group_id; } return $mdb -> query( $sql, $params ) -> fetchColumn(); } static public function get_clicks_30( $product_id, $campaign_id = null, $ad_group_id = null ) { global $mdb; $sql = 'SELECT COALESCE( SUM( clicks ), 0 ) AS total FROM products_history WHERE product_id = :product_id AND date_add >= :date_from'; $params = [ ':product_id' => (int) $product_id, ':date_from' => date( 'Y-m-d', strtotime( '-30 days', time() ) ) ]; if ( $campaign_id !== null ) { $sql .= ' AND campaign_id = :campaign_id'; $params[':campaign_id'] = (int) $campaign_id; } if ( $ad_group_id !== null ) { $sql .= ' AND ad_group_id = :ad_group_id'; $params[':ad_group_id'] = (int) $ad_group_id; } return $mdb -> query( $sql, $params ) -> fetchColumn(); } static public function add_product_comment( $product_id, $comment, $date = null ) { global $mdb; if ( !$date ) $date = date( 'Y-m-d' ); else $date = date( 'Y-m-d', strtotime( $date ) ); if ( $mdb -> count( 'products_comments', [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] ) ) return $mdb -> update( 'products_comments', [ 'comment' => $comment ], [ 'AND' => [ 'product_id' => $product_id, 'date_add' => $date ] ] ); else return $mdb -> insert( 'products_comments', [ 'product_id' => $product_id, 'comment' => $comment, 'date_add' => $date ] ); } static public function get_product_scope_context( $product_id ) { global $mdb; return $mdb -> query( 'SELECT p.id, p.client_id, p.offer_id, p.name, cl.google_ads_customer_id, cl.google_merchant_account_id FROM products AS p INNER JOIN clients AS cl ON cl.id = p.client_id WHERE p.id = :product_id LIMIT 1', [ ':product_id' => (int) $product_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function get_campaign_scope_context( $campaign_id ) { global $mdb; return $mdb -> query( 'SELECT id, client_id, campaign_id, campaign_name FROM campaigns WHERE id = :campaign_id LIMIT 1', [ ':campaign_id' => (int) $campaign_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static public function get_ad_group_scope_context( $ad_group_id ) { global $mdb; return $mdb -> query( 'SELECT id, campaign_id, ad_group_id, ad_group_name FROM campaign_ad_groups WHERE id = :ad_group_id LIMIT 1', [ ':ad_group_id' => (int) $ad_group_id ] ) -> fetch( \PDO::FETCH_ASSOC ); } static private function get_next_local_campaign_external_id( $client_id ) { global $mdb; $min_external_id = (int) $mdb -> query( 'SELECT MIN( campaign_id ) FROM campaigns WHERE client_id = :client_id', [ ':client_id' => (int) $client_id ] ) -> fetchColumn(); if ( $min_external_id < 0 ) { return $min_external_id - 1; } return -1; } static private function get_next_local_ad_group_external_id( $campaign_id ) { global $mdb; $min_external_id = (int) $mdb -> query( 'SELECT MIN( ad_group_id ) FROM campaign_ad_groups WHERE campaign_id = :campaign_id', [ ':campaign_id' => (int) $campaign_id ] ) -> fetchColumn(); if ( $min_external_id < 0 ) { return $min_external_id - 1; } return -1; } static public function create_local_campaign( $client_id, $campaign_name ) { global $mdb; $client_id = (int) $client_id; $campaign_name = trim( (string) $campaign_name ); if ( $client_id <= 0 || $campaign_name === '' ) { return 0; } $existing_campaign_id = (int) $mdb -> get( 'campaigns', 'id', [ 'AND' => [ 'client_id' => $client_id, 'campaign_name' => $campaign_name ] ] ); if ( $existing_campaign_id > 0 ) { return $existing_campaign_id; } $mdb -> insert( 'campaigns', [ 'client_id' => $client_id, 'campaign_id' => self::get_next_local_campaign_external_id( $client_id ), 'campaign_name' => $campaign_name ] ); return (int) $mdb -> id(); } static public function create_local_ad_group( $campaign_id, $ad_group_name ) { global $mdb; $campaign_id = (int) $campaign_id; $ad_group_name = trim( (string) $ad_group_name ); if ( $campaign_id <= 0 || $ad_group_name === '' ) { return 0; } $existing_ad_group_id = (int) $mdb -> get( 'campaign_ad_groups', 'id', [ 'AND' => [ 'campaign_id' => $campaign_id, 'ad_group_name' => $ad_group_name ] ] ); if ( $existing_ad_group_id > 0 ) { return $existing_ad_group_id; } $mdb -> insert( 'campaign_ad_groups', [ 'campaign_id' => $campaign_id, 'ad_group_id' => self::get_next_local_ad_group_external_id( $campaign_id ), 'ad_group_name' => $ad_group_name, 'impressions_30' => 0, 'clicks_30' => 0, 'cost_30' => 0, 'conversions_30' => 0, 'conversion_value_30' => 0, 'roas_30' => 0, 'impressions_all_time' => 0, 'clicks_all_time' => 0, 'cost_all_time' => 0, 'conversions_all_time' => 0, 'conversion_value_all_time' => 0, 'roas_all_time' => 0, 'date_sync' => date( 'Y-m-d' ) ] ); return (int) $mdb -> id(); } static public function assign_product_scope( $product_id, $campaign_id, $ad_group_id ) { global $mdb; $product_id = (int) $product_id; $campaign_id = (int) $campaign_id; $ad_group_id = (int) $ad_group_id; if ( $product_id <= 0 || $campaign_id <= 0 || $ad_group_id <= 0 ) { return false; } $product = self::get_product_scope_context( $product_id ); if ( !$product ) { return false; } $campaign_client_id = (int) $mdb -> get( 'campaigns', 'client_id', [ 'id' => $campaign_id ] ); if ( $campaign_client_id <= 0 || $campaign_client_id !== (int) $product['client_id'] ) { return false; } $ad_group_campaign_id = (int) $mdb -> get( 'campaign_ad_groups', 'campaign_id', [ 'id' => $ad_group_id ] ); if ( $ad_group_campaign_id <= 0 || $ad_group_campaign_id !== $campaign_id ) { return false; } $scope_exists = (int) $mdb -> count( 'products_temp', [ 'AND' => [ 'product_id' => $product_id, 'campaign_id' => $campaign_id, 'ad_group_id' => $ad_group_id ] ] ) > 0; if ( $scope_exists ) { $mdb -> update( 'products_temp', [ 'name' => $product['name'] ], [ 'AND' => [ 'product_id' => $product_id, 'campaign_id' => $campaign_id, 'ad_group_id' => $ad_group_id ] ] ); return true; } return $mdb -> insert( 'products_temp', [ 'product_id' => $product_id, 'campaign_id' => $campaign_id, 'ad_group_id' => $ad_group_id, 'name' => $product['name'], 'impressions' => 0, 'impressions_30' => 0, 'clicks' => 0, 'clicks_30' => 0, 'ctr' => 0, 'cost' => 0, 'conversions' => 0, 'conversions_value' => 0, 'cpc' => 0, 'roas' => 0 ] ); } }