I am currently finishing the website for my client and the only feature and I can't implement is to show the right phone number to a user based on the location.
I tried to find some plugins but no success. Maybe someone can help me with the piece of code I can implement this feature? Thanks!
A couple things.
Since geolocation can be spoofed, ideally you would display all available numbers and have a main number. Or even better have call tracking numbers that are changed via script based on visitor acquisition and referral source.
Barring all of that, you can use a resource like ipstack
You make a request to https://api.ipstack.com/ with the IP Address you want to use ( potentially $_SERVER['REMOTE_ADDR']?) and your access key. So your request URL would like like the following:
$ipstack_url = 'https://api.ipstack.com/123.456.789.001?access_key=YOURACCESSKEYHERE'
WordPress has a built in remote URL function wp_remote_get() that you can use to get this value.
$geo_info = wp_remote_retrieve_body( wp_remote_get( $ipstack_url ) );
To be nice to ipstack (and your request limit), you should probably cache this with the WP_Transients API for at least 24 hours (these results won't change much, so you could cache even longer if you want). You get 10k requests a month for free, so if you have a high traffic site, this is even more important
Now you can do what you want with the ipstack request for that IP address, like display a different phone number based on the current city.
If we combine all of that, you get something like this:
// Get your IP however you want
$ip_addr = $_SERVER['REMOTE_ADDR'];
// You'll need an API Key
$api_key = 'YOURACCESSKEYHERE';
// Build your API URL
$api_url = "https://api.ipstack.com/$ip_addr?access_key=$api_key"; // Build the API Url
// Give your transient a unique, yet identifiable name
$transient_name = "ipstack-$ip_addr";
// Check for our transient, if it's not there set it for 24 hours
if( false === ( $transient = get_transient( $transient_name ) ) ){
set_transient( $transient_name, wp_remote_retrieve_body( wp_remote_get( $api_url ) ), 86400 );
}
// Decode the JSON response we got
$json = json_decode( get_transient( $transient_name ) );
// Do whatever you want with it
if( $json->city == 'Los Angeles' ){
echo 'Phone For LA: 123-456-7890';
} else if( $json->city == 'San Francisco' ){
echo 'Phone For SF: 321-654-0987';
} else {
echo 'Default Phone: 098-765-4321';
}
Related
I'm creating a dashboard for myself that helps me keep track of the Facebook ads I'm running.
What I've not been able to figure out is:
How can I retrieve an array of ad IDs for all ads that are active or could soon be active after no further action on my part?
In other words, I want all ads that I've set to Active and that exist within Adsets and Campaigns that are active (and therefore these ads are live right now)... plus all the ads that from my perspective are Active but that Facebook has set to another status such as Pending Review (and will soon set back to Active).
I have some code below, but the problem is that it also accidentally includes Pending ads that--once reviewed and approved by Facebook--will be inactive rather than active (because I've set them that way). And I do NOT want this type of ad to be included in my report.
My report should only show me ones where I'm actively spending money or have the potential to spend money as soon as FB approves them.
I think I understand the difference between configured_status and effective_status in AbstractArchivableCrudObjectFields, but I don't know that it's enough to help me because I have lots of ads set to Active that are within Adsets that are Inactive, and I don't want to see those listed in my report.
Any recommendations?
public function getActiveAdIds() {
$key = 'activeAdIds';
$adIdsJson = Cache::get($key);
if ($adIdsJson) {
$adIds = json_decode($adIdsJson);
} else {
$adsResponse = $this->getAdsByStatus([ArchivableCrudObjectEffectiveStatuses::ACTIVE, ArchivableCrudObjectEffectiveStatuses::PENDING_REVIEW]);
$ads = $adsResponse->data;
$adIds = [];
foreach ($ads as $ad) {
$adIds[] = $ad->id;
}
$adIdsJson = json_encode($adIds);
Cache::put($key, $adIdsJson, 1);
}
return $adIds;
}
public function getAdsByStatus($statuses) {
$params = [\FacebookAds\Object\Fields\AbstractArchivableCrudObjectFields::EFFECTIVE_STATUS => $statuses];
$adAccount = new AdAccount(self::ACT_PREPEND . $this->fbConfig['account_id']);
$cursor = $adAccount->getAds([], $params);
$response = $cursor->getResponse();
$jsonString = $response->getBody();
return json_decode($jsonString);
}
I get stats based on assets for my active campaigns. I have 119 ad accounts. This is php code which I used it for this purpose (any suggestion to improve it will be appreciated):
$fields = array(AdsInsightsFields::ACCOUNT_NAME,AdsInsightsFields::CAMPAIGN_ID,
AdsInsightsFields::CAMPAIGN_NAME, AdsInsightsFields::ADSET_ID,
AdsInsightsFields::ADSET_NAME,AdsInsightsFields::DATE_START,
AdsInsightsFields::DATE_STOP,AdsInsightsFields::REACH,
AdsInsightsFields::SPEND, AdsInsightsFields::IMPRESSIONS,
AdsInsightsFields::CLICKS, AdsInsightsFields::WEBSITE_CLICKS,
AdsInsightsFields::CALL_TO_ACTION_CLICKS,AdsInsightsFields::ACTIONS,
AdsInsightsFields::TOTAL_ACTIONS,AdsInsightsFields::CPC,
AdsInsightsFields::CPM,AdsInsightsFields::CPP,
AdsInsightsFields::CTR,AdsInsightsFields::OBJECTIVE,);
$params_c['date_preset'] = AdDatePresetValues::YESTERDAY;
$params_c['time_increment'] = 1;
$params_c['action_attribution_windows'] = array('1d_view', '28d_click');
$params_c['effective_status'] = AdStatusValues::ACTIVE;
$params_c['level'] = AdsInsightsLevelValues::ADSET;
$params_c['filtering'] = [array("field"=>"campaign.delivery_info",
"operator"=>"IN",
"value"=>array("active"))];
$params_c['fields']= $fields;
try{
// Initialize a new Session and instanciate an Api object
Api::init(self::api_key, self::secret_token, self::extended_token)->getHttpClient()->setCaBundlePath( $this->path_cert);
// The Api object is now available trough singleton
$api = Api::instance();
$user = new \FacebookAds\Object\Business($business_id);
$user->read(array(BusinessFields::ID));
//get all ad_account from Business
$accounts = $user->getAssignedAdAccounts(
array(
AdAccountFields::ID,
),
array('limit'=>1000,)
);
} catch (FacebookAds\Exception\Exception $ex) {
return $ex->getMessage();
}
if(isset($accounts) && ($accounts->count() > 0)):
do{
$ad_account = $accounts->current();
$adset_insights = $ad_account->getInsights($fields,$params_c);
do {
$adset_insights->fetchAfter();
} while ($adset_insights->getNext());
$adsets = $adset_insights->getArrayCopy(true);
}
while ($accounts->current());
endif;
If you include the adset{end_time} field in the query for the ad, you can assume that ad is not actually running if the end_time was in the past. This is how we get a base list of ads to query on.
The next step we take (which probably won't help you, unfortunately, but may help others) is building a batch of simple requests (one per ad) to see if there are any insights data for that day. If the response is an empty 'data' array, we can remove that ID from the ad list.
After we've reduced the size of the ad list with those two steps we can then make requests to run all of our breakdown reports. This method almost cut our API requests in half.
I have yet to find a way to do a "give me all ads that are for sure running this day" query in one step.
Edit:
I just found a better way to do this.... :
curl -G \
-d 'access_token=<ACCESS_TOKEN>' \
-d 'level=campaign' \
-d 'filtering=[{field:"ad.impressions",operator:"GREATER_THAN",value:0}]' \
'https://graph.facebook.com/v2.7/act_<ACCOUNT_ID>/insights'
I am trying to:
Make a redirect based on the IP of the visitor, i have my website hosted at wpengine and they have a GEO IP service from which i can get the users country based on their IP. If you are coming to the website from sweden,denmark or norway you will not be redirected but stay on page... http://www.centuri.se but if you are not from this countries you will be redirected to the english version of the site which is translated with wpml... so you will go to this page ... http://www.centuri.se/en/ which is the translated one.
I am using this piece of code to make the redirection.
<?php
// THE COOKIE NAME
$cookie_name = "country";
// ACCEPTED COUNTRIES THAT SKIPS THE REDIRECT
$countries = array('se','dk','no');
// CHECK IF YOUR COOKIE IS SET
if (!isset($_COOKIE[$cookie_name])) {
// GET USER INFO
$userInfo = do_shortcode('[geoip-country]');
// GET COUNTRY INTO LOWERCASE
$country = strtolower($userInfo);
//SET COOKIE BASED ON COUNTRY NAME FROM USER
setcookie('country', $country, time() + (3600 * 24 * 30), '/');
if(!in_array($country, $countries)) {
//Set a cookie to tell that this user has been redirected
setcookie('redirect', 1, time() + (3600 * 24 * 30), '/');
wp_redirect( home_url() . '/en/' ); exit;
}
}
?>
On my staging server from wpengine this sollution works flawless, you can test it for yourself http://centuri.staging.wpengine.com but when this script is applied for my live server i am redirected to http://www.centuri.se/en/en and will get an 404 message - i have tried to switch the part of the redirect from home_url() to site_url() instead to see any difference but if i do that on my live server this will give me a redirect loop. I have for now commented this out for my live site since it will make my website crash.
Could this be any setting done in WPML? i don't know really where to go from here... it's so confusing since it's works flawless on my staging server and not my live server and the code and databases are identical.
I haven't tested these but, here are a couple ideas:
1) You might just need to add a check for the current WPML language to make sure you aren't continuing to redirect the user once they are already on the EN site.
2) Your setting a $_COOKIE['redirect'] but not doing anything with it. You could check that where you are checking the other cookie (I'm not sure the cookie will get set and be available immediately though if you are redirecting in a loop).
<?php
// THE COOKIE NAME
$cookie_name = "country";
// ACCEPTED COUNTRIES THAT SKIPS THE REDIRECT
$countries = array('se','dk','no');
// CHECK IF YOUR COOKIE IS SET
if (
!isset( $_COOKIE[$cookie_name] )
// Check redirect cookie??
// && !isset( $_COOKIE['redirect'] )
) {
// GET USER INFO
$userInfo = do_shortcode('[geoip-country]');
// GET COUNTRY INTO LOWERCASE
$country = strtolower($userInfo);
// SET COOKIE BASED ON COUNTRY NAME FROM USER
setcookie('country', $country, time() + (3600 * 24 * 30), '/');
if (
// Don't redirect if current country is in skip list
!in_array($country, $countries)
// Also Check WPML lang code global to make sure the user
// isn't already on the english site
&& ICL_LANGUAGE_CODE !== 'en'
) {
// Set a cookie to tell that this user has been redirected
setcookie( 'redirect', 1, time() + (3600 * 24 * 30), '/' );
wp_redirect( home_url() . '/en/' ); exit;
}
}
I just recently implemented the WPEngine GeoIP check myself, and another thing you might consider is using their PHP Class directly instead of do_shortcode (seems like that is probably working alright for you, but here is another method).
add_action( 'init', 'country_geo_redirect' );
function country_geo_redirect() {
$geo = WPEngine\GeoIp::instance();
$lang = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
if (
!is_admin() && // Let's not redirect the admin panel
!in_array( $GLOBALS['pagenow'], array( 'wp-login.php', 'wp-register.php' ) ) &&
$_SERVER['HTTP_HOST'] !== 'example.com.au' && // Make sure we aren't already on this domain
(
strpos( strtolower( $lang ), 'en-au' ) > -1 // Check the user's browser languages for what we are targeting
|| $geo->country() == 'AU' // Fallback to using WPEngine's GeoIP Check if Browser lang doesn't include en-AU
)
) {
wp_redirect( 'http://example.com' . $_SERVER['REQUEST_URI'] , 301 );
exit;
}
}
You have to keep in mind though, with using their class ($geo = WPEngine\GeoIp::instance();) it isn't able to determine the user's country unless it is run within an init action (if you run it directly in your functions.php file, $country = $geo->country(); will return NULL).
With this second example, I'm also checking the user's browser languages first to see if it includes the target language (en-AU in this case) so that I might be able to skip the GeoIP lookup (in case there is any delay in that lookup) to improve loading speed (haven't actually tested that lookup time yet).
I need a PHP Google search function, so I tried many function I found in Google, but almost all have the same problem which is they take results directly from Google main URL not from the API URL, which lead after a while to an error because Google detect the visits are from a PHP server and reject any further requests.
So I made my Google search function takes results from Google API URL, and that worked perfectly as you see here #API_URL until I needed to reduce the results buy adding intitle: before the searched keyword, and now the API URL return no result at all as you see here #API_URL.
My question is simple, how do I get results in the Google API URL using this query intitle:maleficent+2014+site:www.anakbnet.com/video/file.php?f= so that I can take Results from it using PHP?
The data you get back from your 'Google API' call is json encoded data so you should try something like the following:-
/* define a constant for ease */
define('BR','<br />');
$data='{"responseData": {"results":[{"GsearchResultClass":"GwebSearch","unescapedUrl":"http://www.anakbnet.com/video/file.php?f\u003d1452","url":"http://www.anakbnet.com/video/file.php%3Ff%3D1452","visibleUrl":"www.anakbnet.com","cacheUrl":"http://www.google.com/search?q\u003dcache:9-JgVUvjnGYJ:www.anakbnet.com","title":"مشاهدة فيلم Alexander and the Terrible اون لاين مباشرة بدون تحميل \u003cb\u003e...\u003c/b\u003e","titleNoFormatting":"مشاهدة فيلم Alexander and the Terrible اون لاين مباشرة بدون تحميل ...","content":"29 كانون الثاني (يناير) 2015 \u003cb\u003e...\u003c/b\u003e مشاهدة فيلم \u003cb\u003eMaleficent 2014\u003c/b\u003e DVD HD مترجم اون لاين مباشرة بدون تحميل اكشن ,مغامرة \n,عائلي .. مشاهدة افلام اجنبية مترجمة اونلاين كاملة. (مشاهدة: 491,605 )."}],"cursor":{"resultCount":"1","pages":[{"start":"0","label":1}],
"estimatedResultCount":"1",
"currentPageIndex":0,
"moreResultsUrl":"http://www.google.com/search?oe\u003dutf8\u0026ie\u003dutf8\u0026source\u003duds\u0026start\u003d0\u0026hl\u003den-GB\u0026q\u003dmaleficent+2014+site:www.anakbnet.com/video/file.php?f%3D",
"searchResultTime":"0.09"}},
"responseDetails": null,
"responseStatus": 200}';
$json=json_decode( $data, true );
$res=(object)$json['responseData']['results'][0];
/* two items extracted from data - use same methodology to get other items */
echo $res->unescapedUrl;
echo $res->cacheUrl;
echo '<pre>';
foreach( $json as $key => $param ){
echo $key.BR;
if( is_array( $param )) $param=(object)$param;
print_r( $param );
}
echo '</pre>';
Hopefully from that you can find what you want?!
I want to create couple lists in mailchimp, and I need to have some users in couple lists. I successfully added user to first list, but can't add to second, because I get an error "This user is already subscribed".
I read about segmentation but this doesn't resolve issue, also I see that there is a posibility to copy user from one list to another via mailchimp admin panel, but I can't find which method can do this is in API v2.0
function cog_add_user_email_mailchimp( $user_id ) {
$user_data = get_userdata( $user_id );
if ( is_object( $user_data ) && ! empty( $user_data->user_email ) ) {
$mailchimp_obj = new COG_Mailchimp_Newsletters( MAILCHIMP_APIKEY );
$mailchimp_obj->user_id = $user_id;
$result = $mailchimp_obj->subscibe_user( $mailchimp_obj->lists_id['all_user_list'], array( 'email' => $user_data->user_email ) );
if ( $mailchimp_obj->check_user_subscribe_meta( $result ) ) {
$mailchimp_obj->subscibe_user( $mailchimp_obj->lists_id['just_registered'], array( 'euid' => $result['euid'] ) );
$mailchimp_obj->init_compaing_object( $mailchimp_obj );
$response = $mailchimp_obj->send_mail( $mailchimp_obj->lists_id['just_registered'] );
}
}
}
Where:
$mailchimp_obj->lists_id - array with lists id
$mailchimp_obj->subscibe_user - wrapper for subscribe method of mailchimp API
So I successfully add user into this list $mailchimp_obj->lists_id['all_user_list'], but when I try to subscribe into this list $mailchimp_obj->lists_id['just_registered'] I get an error.
Yes, you can. You'd better use segments inside the same list, though, as using separate lists count your subscribers twice (and, thus, increase the monthly bill).
Now, what have you tried so far? It is good practice to tell the community what code you have tried and didnt work. Or what did you google that yield no desired results but failed ones, etc.
The MailChimp API is a boon to work with. Read the docs.
http://apidocs.mailchimp.com/
I know *wp_remote_get* is a WordPress function, and that I should be posting this in wordpress.stackexchange, however, I am almost certain my issue lies more on the general PHP side.
The problem: I need to retrieve all Vimeo videos found within an album, yet I am only getting 20.
The approach:
$vmg_feed_url = 'http://vimeo.com/api/v2/';
$vmg_user = '2212323';
if($vmg_type == 'user'){ /** just an input variable checking whether the function should search for user or for album. in our case, it searches for album **/
$vmg_type_url = '';
} else {
$vmg_type_url = $vmg_type . '/';
}
$vmg_videos_url = $vmg_feed_url . $vmg_type_url . $vmg_user . '/videos.xml';
$videos_result = wp_remote_get($vmg_videos_url);
$vmg_videos = simplexml_load_string($videos_result['body']);
The resulting XML is http://vimeo.com/api/v2/album/2212323/videos.xml - and as you can see, I am only retrieving 20 videos.
The question: Am I missing something? Is there a function/variable that sets a limit to the amount of videos I can retrieve? I know that wp_remote_get gives me these attributes (from the WordPress Codex):
$url
(string) (required) Universal Resource Locator (URL).
- Default: None
$args
(array) (optional)
- Default: method: GET, timeout: 5, redirection: 5, httpversion: 1.0, blocking: true, headers: array(), body: null, cookies: array()
Any help is truly appreciated. Please let me know if I forgot about any details!
Yor problem is not in wordpress or PHP. It is API limits:
http://developer.vimeo.com/apis/simple
Simple API responses include up to 20 items per page.
You can get more by adding ?page parameter in next requests.