public function process_business_rules_workflow($logger, $config, &$RTBPingerList, \sellrtb\workflows\tasklets\popo\AuctionPopo &$AuctionPopo) { $this->config = $config; $AuctionPopo->auction_was_won = false; // Add Bids to POPO if (\sellrtb\workflows\tasklets\common\AddBids::execute($logger, $this, $RTBPingerList, $AuctionPopo) === false) { return false; } // Make sure that each bid response matches the impression id of the RTB request if (\sellrtb\workflows\tasklets\common\CheckImpId::execute($logger, $this, $AuctionPopo) === false) { return false; } // Adjust the bid amounts with the correct exchange markup if (\sellrtb\workflows\tasklets\common\AdjustBidAmountWithMarkup::execute($logger, $this, $AuctionPopo) === false) { return false; } // Exclude bids that don't meet the floor if (\sellrtb\workflows\tasklets\common\CheckBidFloor::execute($logger, $this, $AuctionPopo) === false) { return false; } // Log and sort bid prices and adjusted bid prices in the case of a second price auction type if (\sellrtb\workflows\tasklets\common\LogBidPrices::execute($logger, $this, $AuctionPopo) === false) { return false; } // Exclude bids that aren't the highest or tied for first place if (\sellrtb\workflows\tasklets\common\CheckHighBid::execute($logger, $this, $AuctionPopo) === false) { return false; } // Exclude partners who's scores aren't the highest or tied for first place if (\sellrtb\workflows\tasklets\common\CheckPartnerScore::execute($logger, $this, $AuctionPopo) === false) { return false; } // Pick a winner from the remaining list of bids if (\sellrtb\workflows\tasklets\common\PickAWinner::execute($logger, $this, $RTBPingerList, $AuctionPopo) === false) { return false; } // if we got here the auction was won $AuctionPopo->auction_was_won = true; $WinningRTBPinger = $AuctionPopo->SelectedPingerList[0]; $seat_bid_list_key = \util\WorkflowHelper::get_first_key($WinningRTBPinger->RtbBidResponse->RtbBidResponseSeatBidList); $bid_list_key = \util\WorkflowHelper::get_first_key($WinningRTBPinger->RtbBidResponse->RtbBidResponseSeatBidList[$seat_bid_list_key]->RtbBidResponseBidList); $WinningRtbResponseBid = $WinningRTBPinger->RtbBidResponse->RtbBidResponseSeatBidList[$seat_bid_list_key]->RtbBidResponseBidList[$bid_list_key]; $bid_price = floatval($WinningRtbResponseBid->price); $WinningRTBPinger->won_auction = true; $WinningRTBPinger->winning_bid = $bid_price; if ($AuctionPopo->ImpressionType == 'video' && empty($WinningRtbResponseBid->adm) && !empty($WinningRtbResponseBid->nurl)) { /* * This is a VAST video ad zone auction and it was won * by a bidder that put a URL to the VAST XML in their * OpenRTB 2.2 nurl param so adm is empty. * * Could be a LiveRail Tag or something. */ /* * We don't need to rawurlencode() the response here before * putting it in the adm field because it never gets used * again. We are putting it in the field for conceptual * parity reasons only. */ $WinningRtbResponseBid->adm = $WinningRtbResponseBid->nurl; $AuctionPopo->winning_ad_tag = $WinningRtbResponseBid->adm; /* * now unset the nurl since we already fired off the impression * and we don't want to fire it off again later. */ unset($WinningRtbResponseBid->nurl); } elseif (!empty($WinningRtbResponseBid->adm)) { $AuctionPopo->winning_ad_tag = rawurldecode($WinningRtbResponseBid->adm); if (!empty($WinningRtbResponseBid->nurl)) { /* * Was there a notice url here? * * Lets fire it off after we have served the output back to the user. * * Store it in the POPO for now. */ $AuctionPopo->nurl = $WinningRtbResponseBid->nurl; } } $AuctionPopo->winning_bid_price = sprintf("%1.4f", $this->encrypt_bid($bid_price)); $AuctionPopo->winning_partner_id = $WinningRTBPinger->partner_id; $popo_seat_bid_key = \util\WorkflowHelper::get_first_key($WinningRTBPinger->RtbBidResponse->RtbBidResponseSeatBidList); $AuctionPopo->winning_seat = $WinningRTBPinger->RtbBidResponse->RtbBidResponseSeatBidList[$popo_seat_bid_key]->seat; /* * Was this a second price auction? * If so record the winning bid */ if ($AuctionPopo->is_second_price_auction === true) { // second price is only tabulated if there is more than 1 valid bid $index = 0; if ($AuctionPopo->bid_price_list > 1) { $index = 1; } $AuctionPopo->second_price_winning_bid_price = $AuctionPopo->bid_price_list[$index]; // second price is only tabulated if there is more than 1 valid bid $index = 0; if ($AuctionPopo->adjusted_bid_price_list > 1) { $index = 1; } $AuctionPopo->second_price_winning_adjusted_bid_price = $AuctionPopo->adjusted_bid_price_list[$index]; } if ($WinningRTBPinger->is_loopback_pinger) { if ($AuctionPopo->ImpressionType == 'video' && empty($WinningRtbResponseBid->adm) && !empty($WinningRtbResponseBid->nurl)) { $ad_tag_to_compare = $WinningRtbResponseBid->nurl; } else { $ad_tag_to_compare = $AuctionPopo->winning_ad_tag; } if (preg_match("/zoneid=(\\d+)/", $ad_tag_to_compare, $matches) && isset($matches[1])) { $AuctionPopo->loopback_demand_partner_ad_campaign_banner_id = $matches[1]; $AuctionPopo->loopback_demand_partner_won = true; } } return $WinningRTBPinger; }
private function process_publisher_tag($config, $banner_request) { $PublisherAdZoneFactory = \_factory\PublisherAdZone::get_instance(); $PublisherWebsiteFactory = \_factory\PublisherWebsite::get_instance(); $params = array(); $params["AdStatus"] = 1; $params["PublisherAdZoneID"] = $banner_request["publisher_banner_id"]; $PublisherAdZone = $PublisherAdZoneFactory->get_row_cached($config, $params); if ($PublisherAdZone == null) { return; } $params = array(); $params["PublisherWebsiteID"] = $PublisherAdZone->PublisherWebsiteID; $PublisherWebsite = $PublisherWebsiteFactory->get_row_cached($config, $params); if ($PublisherWebsite == null) { return; } /* * Does this publisher's website belong to a Domain Admin * running a private exchange? * * If it does, did the domain admin enable this website's inventory * to be available on the platform connection feature to other * domain admins running their own private exchanges? * * Did he enable platform exchange on the website edit page * to enable this publisher's website inventory to be sent to DSPs? */ $banner_request["PrivateExchangeOnly"] = $PublisherWebsite->VisibilityTypeID == 2 ? true : false; $banner_request["ImpressionType"] = $PublisherAdZone->ImpressionType; $banner_request = $this->build_request_array($config, $banner_request); $RtbSellV22Bid = new \rtbsellv22\RtbSellV22Bid(); $RtbSellV22Bid->create_rtb_request_from_publisher_display_impression($config, $banner_request); /* * We build the OpenRTB request destined for demand * that is local to this NginAd instance */ $PmpDealPublisherWebsiteToInsertionOrderLineItemFactory = \_factory\PmpDealPublisherWebsiteToInsertionOrderLineItem::get_instance(); $params = array(); $params["PublisherWebsiteID"] = $PublisherWebsite->PublisherWebsiteID; $params["Enabled"] = 1; if ($banner_request["PrivateExchangeOnly"] === true) { /* * PublisherWebsiteLocal is set to 1 only if the domain admin * owns the publishers under their private exchange */ $params["PublisherWebsiteLocal"] = $PublisherWebsite->VisibilityTypeID == 2 ? 1 : 0; } $PmpDealPublisherWebsiteToInsertionOrderLineItemList = $PmpDealPublisherWebsiteToInsertionOrderLineItemFactory->get_cached($config, $params); $RtbSellV22Bid->clone_local_rtb_request_with_pmp($config, $banner_request, $PmpDealPublisherWebsiteToInsertionOrderLineItemList); $bid_request_list[self::GENERIC_PARTNER] = $RtbSellV22Bid->build_rtb_bid_request_generic(); $bid_request_list[self::LOOPBACK_PARTNER] = $RtbSellV22Bid->build_rtb_bid_request_loopback(); $PingManager = new \pinger\PingManager($config, $bid_request_list, $PublisherAdZone->AdOwnerID, $PublisherAdZone->PublisherWebsiteID, $PublisherAdZone->FloorPrice, $banner_request["PublisherAdZoneID"], $banner_request["AdName"], $banner_request["WebDomain"], $banner_request["ImpressionType"]); /* * Send the RTB request to local demand */ $PingManager->set_up_local_demand_ping_clients(); /* * Only send the RTB request to DSPs if the source * website is not marked for a private exchange only */ if ($banner_request["PrivateExchangeOnly"] === false) { $PingManager->set_up_remote_rtb_ping_clients(); } $PingManager->ping_rtb_ping_clients(); $AuctionPopo = $PingManager->process_rtb_ping_responses(); $auction_was_won = $AuctionPopo->auction_was_won; $winning_ad_tag = $AuctionPopo->winning_ad_tag; /* * Auction stats should be published to the database * regardless of whether there was a winning bid or not. */ $PingManager->process_rtb_ping_statistics($AuctionPopo); /* * The RTB auction may not have been won because * a floor price wasn't met or there simply may not * have been a valid bid on the auction. * * Try to set the tag to the publisher's passback tag * if one exists and if not show the default ad */ if ($auction_was_won === false) { if ($PublisherAdZone->PassbackAdTag != null && !empty($PublisherAdZone->PassbackAdTag)) { $winning_ad_tag = $PublisherAdZone->PassbackAdTag; } else { return; } } else { /* * Process the macro replacements in the winning Ad tag: * * NGINCLKTRK: The click tracking URL, TBD, generic click tracking not yet implemented. * Try implementing your own custom CTR rate tracking * * NGINWBIDPRC: The winning bid price expressed as CPM. * If this was a 2nd price auction, the value would be the second price expressed as CPM */ $winning_ad_tag = str_replace("{NGINCLKTRK}", "", $winning_ad_tag); $winning_ad_tag = str_replace("{NGINWBIDPRC}", $AuctionPopo->winning_bid_price, $winning_ad_tag); } // now output the logs to the log file \rtbsellv22\RtbSellV22Logger::get_instance()->output_log(); $tracker_url = ""; if ($banner_request["ImpressionType"] == 'video' && \util\ParseHelper::isVastURL($winning_ad_tag) === true && $AuctionPopo->auction_was_won) { $encryption_key = $config['settings']['rtb']['encryption_key']; $params = array(); $params["winning_price"] = $AuctionPopo->winning_bid_price; $params["auction_timestamp"] = time(); $vast_auction_param = $this->encrypt_vast_auction_params($encryption_key, $params); $vast_publisher_param = $this->encrypt_vast_auction_params($encryption_key, $AuctionPopo->vast_publisher_imp_obj); $tracker_url = $this->get_vast_tracker_url($config, $vast_auction_param, $vast_publisher_param); $banner_request["tracker_url"] = $tracker_url; } if ($AuctionPopo->loopback_demand_partner_won === true) { $banner_request["demand_banner_id"] = $AuctionPopo->loopback_demand_partner_ad_campaign_banner_id; $banner_request["winning_partner_id"] = $AuctionPopo->winning_partner_id; $banner_request["winning_seat"] = $AuctionPopo->winning_seat; $this->process_demand_tag($config, $banner_request); /* * If this is a local auction we don't need to worry about * firing off notice urls */ } else { if ($banner_request["ImpressionType"] == 'video') { header("Content-type: text/xml"); if (\util\ParseHelper::isVastURL($winning_ad_tag) === true) { echo $this->get_vast_wrapper_xml($config, $winning_ad_tag, $tracker_url); } else { echo $winning_ad_tag; } } else { // credit publisher account here header("Content-type: application/javascript"); $output = "document.write(" . json_encode($winning_ad_tag) . ");"; echo $output; } if (!empty($AuctionPopo->nurl)) { /* * If this is a remote RTB auction we do need to worry about * firing off notice urls * * If safe_mode is off we can fire off an asynchronous CURL * call which will not block. Otherwise we are stuck * with curl call with a timeout. * * curl must also be on the path */ // clear output buffer ob_end_flush(); // check if curl is installed $has_curl_on_path = $config['settings']['shell']['has_curl_on_path']; if (!ini_get('safe_mode') && $has_curl_on_path) { exec('bash -c "exec nohup setsid curl \'' . $AuctionPopo->nurl . '\' > /dev/null 2>&1 &"'); } else { \util\WorkflowHelper::get_ping_notice_url_curl_request($AuctionPopo->nurl); } } } exit; }
private static function get_forensiq_score_from_service($config, $page_to_check, \model\openrtb\RtbBidRequest &$RtbBidRequest) { $forensiq_api_key = $config['settings']['rtb']['forensiq_api_key']; $remote_ip = isset($RtbBidRequest->RtbBidRequestDevice->ip) ? $RtbBidRequest->RtbBidRequestDevice->ip : "unknown"; $domain = isset($RtbBidRequest->RtbBidRequestSite->domain) ? $RtbBidRequest->RtbBidRequestSite->domain : "unknown"; $ua = isset($RtbBidRequest->RtbBidRequestDevice->ua) ? $RtbBidRequest->RtbBidRequestDevice->ua : "unknown"; $pid = isset($RtbBidRequest->RtbBidRequestSite->RtbBidRequestPublisher->name) ? $RtbBidRequest->RtbBidRequestSite->RtbBidRequestPublisher->name : "unknown"; $sid = isset($RtbBidRequest->RtbBidRequestSite->RtbBidRequestPublisher->id) ? $RtbBidRequest->RtbBidRequestSite->RtbBidRequestPublisher->id : "unknown"; $imptype = empty($RtbBidRequestImp->RtbBidRequestVideo) == 'video' ? 'video' : 'display'; $forensiq_url = self::$forensiq_url; $forensiq_url .= '?ck=' . $forensiq_api_key; $forensiq_url .= '&rt=' . $imptype; $forensiq_url .= '&output=JSON'; $forensiq_url .= '&ip=' . $remote_ip; $forensiq_url .= '&url=' . rawurlencode($page_to_check); $forensiq_url .= '&ua=' . rawurlencode($ua); $forensiq_url .= '&seller=' . rawurlencode($domain); $forensiq_url .= '&cmp=' . rawurlencode($pid); $forensiq_url .= '&s=' . rawurlencode($sid); $raw_response = \util\WorkflowHelper::get_ping_notice_url_curl_request($forensiq_url); $forensiq_json_response = json_decode($raw_response, true); return $forensiq_json_response; }
private static function get_traq_score_from_service($config, $page_to_check) { $traq_json_response = self::checkScoreCached($config, $page_to_check); if ($traq_json_response == null) { $traq_url = self::$traq_url . urlencode($page_to_check); $raw_response = \util\WorkflowHelper::get_ping_notice_url_curl_request($traq_url); $traq_json_response = json_decode($raw_response, true); if ($traq_json_response != null) { /* * If we get valid response from the service, * store it for 1 day, so we are not constantly * calling the service with the same parameters */ $params = array(); $params["PageURL"] = $page_to_check; $one_day_in_seconds = 86400; \util\CacheSql::put_cached_read_result_apc($config, $params, self::$class_name, $traq_json_response, $one_day_in_seconds); } } return $traq_json_response; }
protected function logImpressionsStatisticsData($tld, $total_bids, $spend_offered_in_bids) { if ($this->RtbBidRequest != null) { /* * CREATE AN HOURLY TALLY OF INCOMING RTB BIDS * FROM BOTH LOCAL PUBS AND REMOTE SSP RTB SITE ID * CHANNELS IN ORDER TO PROVIDE THE SITE SCOUT * RTB CHANNEL CHOOSER FUNCTIONALITY IN AN EXCEL LIKE * GRID LAYOUT WITH THE DAILY IMPS IN A SORTABLE COLUMN */ $buyside_partner_name = $this->rtb_ssp_friendly_name; $rtb_channel_site_domain = $tld; $auction_bids_counter = $total_bids; $rtb_ids = \util\WorkflowHelper::getIdsFromRtbRequest($this->RtbBidRequest); $rtb_channel_site_id = $rtb_ids["rtb_channel_site_id"]; $rtb_channel_site_name = $rtb_ids["rtb_channel_site_name"]; $rtb_channel_publisher_name = $rtb_ids["rtb_channel_publisher_name"]; $rtb_channel_site_iab_category = $rtb_ids["rtb_channel_site_iab_category"]; $impressions_offered_counter = $rtb_ids["impressions_offered_counter"]; $floor_price_if_any = 0; if (isset($this->RtbBidRequest->RtbBidRequestImpList) && is_array($this->RtbBidRequest->RtbBidRequestImpList)) { foreach ($this->RtbBidRequest->RtbBidRequestImpList as $RtbBidRequestImp) { if (isset($RtbBidRequestImp->bidfloor) && $RtbBidRequestImp->bidfloor > $floor_price_if_any) { $floor_price_if_any = floatval($RtbBidRequestImp->bidfloor); } } } $method_params = array("buyside_partner_name" => $buyside_partner_name, "rtb_channel_site_id" => $rtb_channel_site_id, "rtb_channel_site_name" => $rtb_channel_site_name, "rtb_channel_site_domain" => $rtb_channel_site_domain, "rtb_channel_site_iab_category" => $rtb_channel_site_iab_category, "rtb_channel_publisher_name" => $rtb_channel_publisher_name, "impressions_offered_counter" => $impressions_offered_counter, "auction_bids_counter" => $auction_bids_counter, "spend_offered_in_bids" => $spend_offered_in_bids, "floor_price_if_any" => $floor_price_if_any); if ($this->is_local_request === true) { /* * In the local context, $rtb_channel_site_id is the PublisherWebsiteID */ $PrivateExchangeRtbChannelDailyStatsFactory = \_factory\PrivateExchangeRtbChannelDailyStats::get_instance(); $PrivateExchangeRtbChannelDailyStatsFactory->incrementPrivateExchangeRtbChannelDailyStatsCached($this->config, $method_params); } else { $SspRtbChannelDailyStatsFactory = \_factory\SspRtbChannelDailyStats::get_instance(); $SspRtbChannelDailyStatsFactory->incrementSspRtbChannelDailyStatsCached($this->config, $method_params); } } }
private function process_publisher_tag($config, $banner_request) { $PublisherAdZoneFactory = \_factory\PublisherAdZone::get_instance(); $params = array(); $params["AdStatus"] = 1; $params["PublisherAdZoneID"] = $banner_request["publisher_banner_id"]; $PublisherAdZone = $PublisherAdZoneFactory->get_row_cached($config, $params); if ($PublisherAdZone == null) { return; } $banner_request["ImpressionType"] = $PublisherAdZone->ImpressionType; /* * Is this ad zone linked to one or more contract banners? * If so forward the request to the contract banner * display probability logic. */ if ($PublisherAdZone->PublisherAdZoneTypeID == AD_TYPE_CONTRACT) { $LinkedBannerToAdZoneFactory = \_factory\LinkedBannerToAdZone::get_instance(); $params = array(); $params["PublisherAdZoneID"] = $banner_request["publisher_banner_id"]; $LinkedBannerToAdZoneList = $LinkedBannerToAdZoneFactory->get_cached($config, $params); if ($LinkedBannerToAdZoneList != null && count($LinkedBannerToAdZoneList) > 0) { $this->process_contract_zone_tag($config, $banner_request, $LinkedBannerToAdZoneList); } else { return; } } else { $banner_request = $this->build_request_array($config, $banner_request); $RtbSellV22Bid = new \rtbsellv22\RtbSellV22Bid(); $RtbSellV22Bid->create_rtb_request_from_publisher_display_impression($config, $banner_request); $bid_request = $RtbSellV22Bid->build_rtb_bid_request(); $PingManager = new \pinger\PingManager($config, $bid_request, $PublisherAdZone->AdOwnerID, $PublisherAdZone->PublisherWebsiteID, $PublisherAdZone->FloorPrice, $banner_request["PublisherAdZoneID"], $banner_request["AdName"], $banner_request["WebDomain"], $banner_request["ImpressionType"]); if ($PublisherAdZone->PublisherAdZoneTypeID == AD_TYPE_IN_HOUSE_REMNANT || $PublisherAdZone->PublisherAdZoneTypeID == AD_TYPE_ANY_REMNANT) { $PingManager->set_up_local_demand_ping_clients(); } if ($PublisherAdZone->PublisherAdZoneTypeID == AD_TYPE_RTB_REMNANT || $PublisherAdZone->PublisherAdZoneTypeID == AD_TYPE_ANY_REMNANT) { $PingManager->set_up_remote_rtb_ping_clients(); } $PingManager->ping_rtb_ping_clients(); $AuctionPopo = $PingManager->process_rtb_ping_responses(); $auction_was_won = $AuctionPopo->auction_was_won; $winning_ad_tag = $AuctionPopo->winning_ad_tag; /* * Auction stats should be published to the database * regardless of whether there was a winning bid or not. */ $PingManager->process_rtb_ping_statistics($AuctionPopo); /* * The RTB auction may not have been won because * a floor price wasn't met or there simply may not * have been a valid bid on the auction. * * Try to set the tag to the publisher's passback tag * if one exists and if not show the default ad */ if ($auction_was_won === false) { if ($PublisherAdZone->PassbackAdTag != null && !empty($PublisherAdZone->PassbackAdTag)) { $winning_ad_tag = $PublisherAdZone->PassbackAdTag; } else { return; } } else { /* * Process the macro replacements in the winning Ad tag: * * NGINCLKTRK: The click tracking URL, TBD, generic click tracking not yet implemented. * Try implementing your own custom CTR rate tracking * * NGINWBIDPRC: The winning bid price expressed as CPM. * If this was a 2nd price auction, the value would be the second price expressed as CPM */ $winning_ad_tag = str_replace("{NGINCLKTRK}", "", $winning_ad_tag); $winning_ad_tag = str_replace("{NGINWBIDPRC}", $AuctionPopo->winning_bid_price, $winning_ad_tag); } // now output the logs to the log file \rtbsellv22\RtbSellV22Logger::get_instance()->output_log(); $tracker_url = ""; if ($banner_request["ImpressionType"] == 'video' && \util\ParseHelper::isVastURL($winning_ad_tag) === true && $AuctionPopo->auction_was_won) { $encryption_key = $config['settings']['rtb']['encryption_key']; $params = array(); $params["winning_price"] = $AuctionPopo->winning_bid_price; $params["auction_timestamp"] = time(); $vast_auction_param = $this->encrypt_vast_auction_params($encryption_key, $params); $vast_publisher_param = $this->encrypt_vast_auction_params($encryption_key, $AuctionPopo->vast_publisher_imp_obj); $tracker_url = $this->get_vast_tracker_url($config, $vast_auction_param, $vast_publisher_param); $banner_request["tracker_url"] = $tracker_url; } if ($AuctionPopo->loopback_demand_partner_won === true) { $banner_request["demand_banner_id"] = $AuctionPopo->loopback_demand_partner_ad_campaign_banner_id; $banner_request["winning_partner_id"] = $AuctionPopo->winning_partner_id; $banner_request["winning_seat"] = $AuctionPopo->winning_seat; $this->process_demand_tag($config, $banner_request); /* * If this is a local auction we don't need to worry about * firing off notice urls */ } else { if ($banner_request["ImpressionType"] == 'video') { header("Content-type: text/xml"); if (\util\ParseHelper::isVastURL($winning_ad_tag) === true) { echo $this->get_vast_wrapper_xml($config, $winning_ad_tag, $tracker_url); } else { echo $winning_ad_tag; } } else { // credit publisher account here header("Content-type: application/javascript"); $output = "document.write(" . json_encode($winning_ad_tag) . ");"; echo $output; } if (!empty($AuctionPopo->nurl)) { /* * If this is a remote RTB auction we do need to worry about * firing off notice urls * * If safe_mode is off we can fire off an asynchronous CURL * call which will not block. Otherwise we are stuck * with curl call with a timeout. * * curl must also be on the path */ // clear output buffer ob_end_flush(); // check if curl is installed $has_curl_on_path = $config['settings']['shell']['has_curl_on_path']; if (!ini_get('safe_mode') && $has_curl_on_path) { exec('bash -c "exec nohup setsid curl \'' . $AuctionPopo->nurl . '\' > /dev/null 2>&1 &"'); } else { \util\WorkflowHelper::get_ping_notice_url_curl_request($AuctionPopo->nurl); } } } } exit; }