Deleting completed Facebook AdSets using Marketing API - php

I am trying to create Facebook Ads cleaner, which deletes completed AdSets in a specified campaign. There's a limit how may non-deleted non-archived AdSets you can have (which is 10000 for bulk accounts), and we are reaching this limit quite quickly.
I am using Marketing API, and Facebook Ads API SDK for PHP:
https://github.com/facebook/facebook-php-ads-sdk
While it is clear how AdSets can be retrieved, I can't find a way to filter them by end time. There is a "since" parameter, but it looks like it doesn't filter on AdSet start and end date, and rather filters stats themselves. Therefore AdSet, which is still active, will get into specified range.
My code:
use FacebookAds\Object\Campaign;
use FacebookAds\Object\Fields\AdSetFields;
use Carbon\Carbon;
// Facebook ID of a Ad Campaign
$external_id = '123456789';
$campaign = new Campaign( $external_id );
// Querying required field only
$fields = [
AdSetFields::END_TIME
];
// Need to query AdSets which have been completed in the past...?
$params = [
];
$adsets = $campaign->getAdSets( $fields, $params );
$adsets->setUseImplicitFetch( true );
while ( $adsets->valid() )
{
/** #var AdSet $adset */
$adset = $adsets->current();
$end_time = Carbon::parse( $adset->{AdSetFields::END_TIME} );
if ( $end_time->isPast() )
{
$adset->delete();
}
$adsets->next();
}
The problem: in case there are lots of AdSets in a Campaign, this will literally mean iterating ALL AdSets inside one-by-one and checking it's end date. Usually, we're speaking about thousands of records, and such approach is highly ineffective. As we have lots of ad accounts, "cleaning" script runs forever, even if it doesn't timeout quickly.
Question: is there a way to filter AdSets by end_time? It looks like it is possible by explicitly proving a value, but I can't find a way to filter value using "less than" or "more than" syntax.

If adset has completed running, the its effective status will be in 'PAUSED' state. This should return a smaller subset of adsets. You can filter adsets in the PAUSED state and then check for their end time and delete after validation.

Related

Getting a corporate account id from new Memberpress transaction (non subscription)

I'm using Memberpress and Memberpress Corporate on my WordPress site and I'm trying to add a custom function when a member signs up under a specific membership type or purchases a specific membership type. When this happens I need to grab the corporate account ID and do something with it.
I'm using the hook mepr-event-transaction-completed as this fires for both recurring and non-recurring transactions, though I also tried mepr-event-non-recurring-transaction-completed just to be sure.
This is my code:
$transaction = $event->get_data();
$membership_type_ids = array(1, 2, 4);
if (in_array($transaction->product_id, $membership_type_ids) && $transaction->txn_type == 'payment') {
$org_id = $transaction->corporate_account_id;
my_custom_function($org_id);
}
When the user is signing up for this membership type with a subscription, this is no problem, I can retrieve this, however if they are signing up with a one-time non-recurring transaction, the corporate account id is returning as 0, even though when I go to check the database, there is a corporate account id there.
Does the corporate account id get set at a different time for non-recurring transactions?
Okay, so after speaking to Memberpress, it turns out this just doesn't get set at the right time.
I used a workaround as so:
if($transaction->corporate_account_id !== "0" && $transaction->corporate_account_id !== 0) {
//some irrelevant code here about what to do if the corporate id actually works
} else {
write_log('sending cron to add new user due to corporate id returning as 0, please check in 2 minutes. tran_num = '.$transaction->trans_num);
wp_schedule_single_event( strtotime("+2 minutes"), 'send_fix_for_zero_transaction', array($transaction),false );
return;
}
add_action( 'send_fix_for_zero_transaction', 'single_transaction_create_corporate' );
function single_transaction_create_corporate($transaction) {
//NOTE: this function is only used it a one-time transaction is created in the backend to create a corporate membership, because there is a bug in memberpress that means the corporate_id isn't sent back by the event. This event will only fire if that is the case, otherwise this is handled by rc_setup_new_org. This should eventually be deprecated when Memberpress fix their issues.
$trans_num = $transaction->trans_num;
$full_trans = MeprTransaction::get_one_by_trans_num($trans_num);
//do whatever you need to do with the transaction here, you have the number now
}

Issues Fetching Proper Listings' Data Using RETS

I am trying tot download a live feed of property listings from the CREA's DDF. I am making an API request via PHP to their DDF and am pulling and downloading all the recent listings into my DB. This works fine, the issue is my clients listings which are in the DDF and should be pulled with all the other listings are not being pulled. I seem to get what it seems like all the listings for the surrounding area, but maybe not since I can't receive my client's listings which should be a part of the pull. When I talked to CREA people they said my clients listings are in the DDF so I should be able to pull them with all the other listings. I was hoping to get some advice from some people who have a better understanding of making request like this, or even better using CREA's DDF.
I will provide my code below, I will try to only include stuff that would be relevant and take out the unnecessary code to make this a little easier. If you want to see more of the code, I will add those parts on request.
If I understand correctly I need to add onto my paramaters array but I really dont know why my request is doing this so any help would be awesome!
Here is the code for my download.php file
$TimeBackPull = "-24 hours";
/* RETS Variables */
require("PHRets_CREA.php");
$RETS = new PHRets();
$RETSURL = "http://data.crea.ca/Login.svc/Login";
$RETSUsername = "**********************";
$RETSPassword = "**********************";
$RETS->Connect($RETSURL, $RETSUsername, $RETSPassword);
$RETS->AddHeader("RETS-Version", "RETS/1.7.2");
$RETS->AddHeader('Accept', '/');
$RETS->SetParam('compression_enabled', true);
$RETS_PhotoSize = "LargePhoto";
$RETS_LimitPerQuery = 100;
if($debugMode /* DEBUG OUTPUT */)
{
$RETS->SetParam("catch_last_response", true);
$RETS->SetParam("debug_file", "CREA_Anthony.txt");
$RETS->SetParam("debug_mode", true);
}
$DBML = "(LastUpdated=" . date('Y-m-d', strtotime($TimeBackPull)) . ")";
$params = array("Limit" => 1, "Format" => "STANDARD-XML", "Count" => 1);
$results = $RETS->SearchQuery("Property", "Property", $DBML, $params);
$totalAvailable = $results["Count"];
for($i = 0; $i < ceil($totalAvailable / $RETS_LimitPerQuery); $i++)
{
$startOffset = $i*$RETS_LimitPerQuery;
$params = array("Limit" => $RETS_LimitPerQuery, "Format" => "STANDARD-XML", "Count" => 1, "Offset" => $startOffset);
$results = $RETS->SearchQuery("Property", "Property", $DBML, $params);
foreach($results["Properties"] as $listing)
{
//Do Some Stuff
}
}
Here is what my current request looks like in the return xml file
http://data.crea.ca/Search.svc/Search?SearchType=Property&Class=Property&Query=%28LastUpdated%3D2015-09-22%29&QueryType=DMQL2&Count=1&Format=STANDARD-XML&Limit=1&StandardNames=0
Another thing is that the CREA people said there should be around 1900 active listings to pull but when I count the results I only get around 182 right now
Did you get this resolved?
CREA DDF is weird animal. They only partially support the RETS spec, not fully. They've designed their system around "Destinations" (aka, "Data Feeds") and "Tech Provider" separations.
1) Each of your clients creates one or more data feeds, each of which is assigned a unique DestinationID. When setting up the feed, they select you as the Tech Provider, so their listings get included in your feed, too.
2) You, as the tech provider, have a single feed where you can pull all listings across all of your clients. Where this breaks down, though, is that each listing does not reference which feed/destination that it belongs to. You need to pull data in the context of a particular destination, and then manually associate the current DestinationID with the listings that come through.
CREA thinks that they've made it simpler by having a single Tech Provider feed, but they've actually made it more difficult because they are providing incomplete data on the responses. You, as the developer, need to manually do the associations at your end.
Are your clients selecting you as their Technology Provider during the setup of their Data Feeds? Do you see their feeds show in your Destinations table?

Instagram API to fetch all photo in php

i'm using this api:
public function getUserMedia($id = 'self', $limit = 0) {
return $this->_makeCall('users/'.$id.'/media/recent', true, array('count' => $limit));
}
to fetch the photo of a user logged in my site using php
it works, and all other api works.
the problem is that i want to retrieve ALL the photo of a user (such as printstagr.am).
i've searched in the api but without success: it seems that you can take the recents or the populars, but the site mentioned above takes all. any idea?
thanks!
Not sure what the max count is (saw someone mention 20 was the max on another question, but can't find any limit in the docs from a quick scan), but essentially what you have to do is request as many as possible, then follow the pagination links to collect more.
So from the api docs they provide this:
{
...
"pagination": {
"next_url": "https://api.instagram.com/v1/tags/puppy/media/recent?access_token=fb2e77d.47a0479900504cb3ab4a1f626d174d2d&max_id=13872296",
"next_max_id": "13872296"
}
}
Your application needs to store the objects from the request (i.e. an array), then fire a new request to the "next_url", put those objects into the same store (i.e. array), then follow the link again, until you reach the end or until you get enough to satisfy your needs.

How can I create a RSS feed with a limit statement in wordpress

I am basically creating an iphone app that get's it's data from wordpress. Wordpress will serve audio and video links via a RSS feed to the iphone app. I have the feed and audio player working great but can't seem to find anything related to how to create a custom feed where I can specify pagination like start=0&items=10. A plugin would be great but I can code something up in PHP if anyone has any ideas.
I'm going to answer this question by changing the standard RSS feed of a WordPress installation to respond to limits passed by query parameters. As you say you've already got a working feed, this should hopefully give you everything else you need.
By default, the standard feeds in WordPress are limited by the setting "Syndication feeds show the most recent X items" on the Settings→Reading page, and are unpaginated, as that wouldn't generally make sense for an RSS feed. This is controlled by WordPress's WP_Query::get_posts() method, in query.php, if you're interested in taking a look at how things work internally.
However, although the feed query's limit is set to LIMIT 0, X (where X is the above setting, 10 by default) , you can override the limit by filtering the query in the right place.
For example, the filter post_limits will filter the LIMIT clause of the query between the point it's set up by the default code for feeds and the time it's run. So, the following code in a plugin -- or even in your theme's functions.php -- will completely unlimit the items returned in your RSS feeds:
function custom_rss_limits($limits) {
if (is_feed()) {
// If this is a feed, drop the LIMIT clause completely
return "";
} else {
// It's not a feed; leave the normal LIMIT in place.
return $limits;
}
}
add_filter('post_limits', 'custom_rss_limits');
(At this point I should mention the obvious security implications -- if you've got 20,000 posts on your blog, you'll cause yourself a lot of server load and bandwidth if if lots of people start grabbing your feed, and you send out all 20,000 items to everyone. Therefore, bear in mind that whatever you end up doing, you may still want to enforce some hard limits, in case someone figures out your feed endpoint can be asked for everything, say by analysing traffic from your iPhone app.)
Now all we've got to do is to respond to query parameters. First of all, we register your two query parameters with WordPress:
function rss_limit_queryvars( $qv ) {
$qv[] = 'start';
$qv[] = 'items';
return $qv;
}
add_filter('query_vars', 'rss_limit_queryvars' );
That allows us to pass in the start and items variables you're suggesting for your URL parameters.
All we have to do then is to adjust our original LIMIT changing function to respond to them:
function custom_rss_limits($limits) {
if (is_feed()) {
global $wp_query;
if (isset($wp_query->query_vars['start']) &&
isset($wp_query->query_vars['items'])) {
// We're a feed, and we got pagination parameters. Override our
// standard limit.
// First convert to ints in case anyone's put something hinky
// in the query string.
$start = intval($wp_query->query_vars['start']);
$items = intval($wp_query->query_vars['items']);
$limits = "LIMIT $start, $items";
} else {
// We weren't passed pagination parameters, so just
// leave the default limits alone.
}
}
return $limits;
}
add_filter('post_limits', 'custom_rss_limits');
And there you go. Throw those last two blocks of code at WordPress, and you can now use a URL like this on any of your existing feeds:
http://example.com/feed/?start=30&items=25
For this example, you'll get the normal RSS feed, but with 25 items starting from item number 30.
...and if you don't pass the query parameters, everything will work like normal.

Using Google Analytics API with PHP

I am using the Google Analytics PHP class to get data from Google Analytics.
http://code.google.com/p/gapi-google-analytics-php-interface/wiki/GAPIDocumentation
I would like to get a report of "Bounce Rate" For "Top Contnet".
The thing is I am not familiar with the terminology.
When I am trying to get a "content" report or "topcontent" or "top_content" it says that there in no such metric. I simply don't know the right expressions.
Does anyone know where can I find a list of all expressions? metrics & dimensions?
Thanks.
Top content isn't a metric, it's just a list of the pages on your site with the highest number of page views.
The metric you're looking for is 'entranceBounceRate' and the dimension is 'pagePath'. You want to get the bounce rate for the top X most visited pages on your site, so you'll want to limit your results and sort the results by '-pageviews' (pageviews descending).
If you want to get the bounce rate for the top 10 most viewed pages on your site, your query should look like this:
$ga = new gapi('email#yourdomain.com','password');
$ga->requestReportData(145141242,array('pagePath'),array('entranceBounceRate','pageviews'),array('-visits'),null,null,null,10);
The Google Analytics Export API has a data feed query explorer that should help you out considerably when using GAPI:
http://code.google.com/apis/analytics/docs/gdata/gdataExplorer.html
Also, here's a list of all available dimensions and metrics you can pull from the API:
http://code.google.com/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html
Definitely read over the GAPI documentation:
http://code.google.com/p/gapi-google-analytics-php-interface/wiki/GAPIDocumentation
If you would like to get the global Bounce Rate for the last 30days (by default), here is how. Very simple once you know it.
//Check Bounce Rate for the last 30 days
$ga = new gapi(ga_email, ga_password);
$ga->requestReportData(145141242, NULL ,array('bounces', 'visits'));
$data = round(($ga->getBounces() / $ga->getVisits()) * 100) . "%";
Note that the GAPI has a bug, they mention the dimension parameter is optional (2nd parameter) but it's not. You have to open the gapi.class.php file and patch line 128 with this:
//Patch bug to make 2nd parameter optional
if( !empty($dimensions) ) {
$parameters['dimensions'] = 'ga:'.$dimensions;
} else {
$parameters['dimensions'] = '';
}

Categories